From f32ebbb2974ba7d8318c8126f64f4a73a64d1fb0 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 12 Jun 2025 16:23:37 -0600 Subject: [PATCH 01/36] Flash Unite and HDA Flowsheet Tutorial Revisions to reflect changes to initialization and scaling --- .../notebooks/docs/tut/core/flash_unit.ipynb | 1584 +++++- .../docs/tut/core/flash_unit_doc.ipynb | 3412 ++++++------- .../docs/tut/core/flash_unit_exercise.ipynb | 731 ++- .../docs/tut/core/flash_unit_solution.ipynb | 1536 +++++- .../docs/tut/core/flash_unit_test.ipynb | 1324 ++++- .../docs/tut/core/flash_unit_usr.ipynb | 1536 +++++- .../docs/tut/core/hda_flowsheet.ipynb | 2407 +++++++-- .../docs/tut/core/hda_flowsheet_doc.ipynb | 4057 ++++++++++----- .../tut/core/hda_flowsheet_exercise.ipynb | 4038 ++++++++++----- .../tut/core/hda_flowsheet_solution.ipynb | 4522 +++++++++++------ .../docs/tut/core/hda_flowsheet_test.ipynb | 4362 ++++++++++------ .../docs/tut/core/hda_flowsheet_usr.ipynb | 4522 +++++++++++------ 12 files changed, 23652 insertions(+), 10379 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index 6dc88109..2fe01927 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,50 +527,70 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "code", - "execution_count": 13, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.334804Z", + "start_time": "2025-06-06T16:45:50.327991Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 7" - ] + ], + "outputs": [], + "execution_count": 19 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -373,7 +627,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -381,30 +645,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -416,11 +686,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -429,93 +713,161 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "code", - "execution_count": 18, "metadata": { "tags": [ "testing" ] }, + "cell_type": "code", "outputs": [], + "execution_count": 24, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -523,58 +875,140 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "code", - "execution_count": 23, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.975773Z", + "start_time": "2025-06-06T17:04:32.972754Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ - "# Check for optimal solution\n", + "# Check for an optimal solution\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert status.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 38 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -594,10 +1028,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -607,38 +1044,95 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "code", - "execution_count": 26, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:39.229802Z", + "start_time": "2025-06-06T17:04:39.132903Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check optimal solution values\n", "import pytest\n", @@ -662,13 +1156,15 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(368, abs=1e-3)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 41 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -680,22 +1176,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -703,14 +1212,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -723,22 +1230,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -746,7 +1253,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -754,18 +1261,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -778,7 +1288,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -809,11 +1319,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -822,27 +1565,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -875,18 +1618,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -894,14 +1866,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -917,17 +1891,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -946,17 +2021,110 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check for solver status\n", "assert status.solver.termination_condition == TerminationCondition.optimal\n", @@ -981,7 +2149,9 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(369.07, abs=1e-2)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": null } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 9432ccbe..5f3b9777 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -1,1912 +1,1590 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Flash Unit Model\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", - "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", - "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", - "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", - "\n", - "## Key links to documentation\n", - "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", - "\n", - "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", - "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to perform the imports. Let a workshop organizer know if you see any errors.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", - "from idaes.core import FlowsheetBlock\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to create the objects\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Use the pprint method on the model, i.e. m.pprint(), to see what is currently contained in the model.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 Block Declarations\n", - " fs : Size=1, Index=None, Active=True\n", - " 1 Set Declarations\n", - " _time : Size=1, Index=None, Ordered=Insertion\n", - " Key : Dimen : Domain : Size : Members\n", - " None : 1 : Any : 1 : {0.0,}\n", - "\n", - " 1 Declarations: _time\n", - "\n", - "1 Declarations: fs\n" - ] - } - ], - "source": [ - "# Todo: call pprint on the model\n", - "m.pprint()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define Properties\n", - "\n", - "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", - "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", - "\n", - "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the following two cells to import and create the properties block.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", - " BTXParameterBlock,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.properties = BTXParameterBlock(\n", - " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Flash Unit\n", - "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", - "\n", - "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", - "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", - "\n", - "Some of the IDAES pre-written unit models:\n", - "* Mixer / Splitter\n", - "* Heater / Cooler\n", - "* Heat Exchangers (simple and 1D discretized)\n", - "* Flash\n", - "* Reactors (kinetic, equilibrium, gibbs, stoichiometric conversion)\n", - "* Pressure changing equipment (compressors, expanders, pumps)\n", - "* Feed and Product (source / sink) components\n", - "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the following two cells to import the Flash and create an instance of the unit model, attaching it to the flowsheet object.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Set Operating Conditions\n", - "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", - "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", - "\n", - "degrees_of_freedom(block)\n", - " Method to return the degrees of freedom of a model.\n", - " \n", - " Args:\n", - " block : model to be studied\n", - " \n", - " Returns:\n", - " Number of degrees of freedom in block.\n", - "\n" - ] - } - ], - "source": [ - "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Todo: Call the python help on the degrees_of_freedom function\n", - "help(degrees_of_freedom)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now print the degrees of freedom for your model. The result should be 7.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Degrees of Freedom = 7\n" - ] - } - ], - "source": [ - "# Todo: print the degrees of freedom for your model\n", - "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", - "\n", - "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", - "\n", - "As an example, to fix the molar flow of the inlet to be 1.0, you can use the following notation:\n", - "```python\n", - "m.fs.flash.inlet.flow_mol.fix(1.0)\n", - "```\n", - "\n", - "To specify variables that are indexed by components, you can use the following notation:\n", - "```python\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", - "```\n", - "\n", - "
\n", - "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", - "
\n", - "\n", - "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", - "\n", - "\n", - "To specify the value of a variable on the unit itself, use the following notation.\n", - "\n", - "```python\n", - "m.fs.flash.heat_duty.fix(0)\n", - "```\n", - "\n", - "For this module, we will use the following specifications:\n", - "* inlet overall molar flow = 1.0 (`flow_mol`)\n", - "* inlet temperature = 368 K (`temperature`)\n", - "* inlet pressure = 101325 Pa (`pressure`)\n", - "* inlet mole fraction (benzene) = 0.5 (`mole_frac_comp[0, \"benzene\"]`)\n", - "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", - "* The heat duty on the flash set to 0 (`heat_duty`)\n", - "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Write the code below to specify the inlet conditions and unit specifications described above\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add inlet specifications given above\n", - "m.fs.flash.inlet.flow_mol.fix(1)\n", - "m.fs.flash.inlet.temperature.fix(368)\n", - "m.fs.flash.inlet.pressure.fix(101325)\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"toluene\"].fix(0.5)\n", - "\n", - "# Todo: Add 2 flash unit specifications given above\n", - "m.fs.flash.heat_duty.fix(0)\n", - "m.fs.flash.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Check the degrees of freedom again to ensure that the system is now square. You should see that the degrees of freedom is now 0.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Degrees of Freedom = 0\n" - ] - } - ], - "source": [ - "# Todo: print the degrees of freedom for your model\n", - "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initializing the Model\n", - "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: State Released.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume: Initialization Complete\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: State Released.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash: Initialization Complete: optimal - Optimal Solution Found\n" - ] - } - ], - "source": [ - "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: \n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 135\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 72\n", - "\n", - "Total number of variables............................: 41\n", - " variables with only lower bounds: 3\n", - " variables with lower and upper bounds: 10\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 41\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.46e-11 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - "\n", - "Number of Iterations....: 0\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.6292494973376915e-12 1.4551915228366852e-11\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.6292494973376915e-12 1.4551915228366852e-11\n", - "\n", - "\n", - "Number of objective function evaluations = 1\n", - "Number of objective gradient evaluations = 1\n", - "Number of equality constraint evaluations = 1\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 1\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 0\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.000\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n", - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - ] - } - ], - "source": [ - "# Todo: create the ipopt solver\n", - "solver = SolverFactory(\"ipopt\")\n", - "\n", - "# Todo: solve the model\n", - "status = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Viewing the Results\n", - "\n", - "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", - "```python\n", - "print('Vap. Outlet Temperature = ', value(m.fs.flash.vap_outlet.temperature[0]))\n", - "```\n", - "\n", - "You can also find more information about a variable or an entire port using the `display` method from Pyomo:\n", - "```python\n", - "m.fs.flash.vap_outlet.temperature.display()\n", - "m.fs.flash.vap_outlet.display()\n", - "```\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cells below to show the current value of the flash vapor outlet pressure. This cell also shows use of the display function to see the values of the variables in the vap_outlet and the liq_outlet.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pressure = 101325.0\n", - "\n", - "Output from display:\n", - "vap_outlet : Size=1\n", - " Key : Name : Value\n", - " None : flow_mol : {0.0: 0.39611817487741735}\n", - " : mole_frac_comp : {(0.0, 'benzene'): 0.6339766485081294, (0.0, 'toluene'): 0.36602335149187054}\n", - " : pressure : {0.0: 101325.0}\n", - " : temperature : {0.0: 368.0}\n", - "liq_outlet : Size=1\n", - " Key : Name : Value\n", - " None : flow_mol : {0.0: 0.6038818251225827}\n", - " : mole_frac_comp : {(0.0, 'benzene'): 0.4121175977229309, (0.0, 'toluene'): 0.587882402277069}\n", - " : pressure : {0.0: 101325.0}\n", - " : temperature : {0.0: 368.0}\n" - ] - } - ], - "source": [ - "# Print the pressure of the flash vapor outlet\n", - "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", - "\n", - "print()\n", - "print(\"Output from display:\")\n", - "# Call display on vap_outlet and liq_outlet of the flash\n", - "m.fs.flash.vap_outlet.display()\n", - "m.fs.flash.liq_outlet.display()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.flash Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 0.0000 : watt : True : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol mole / second 1.0000 0.39612 0.60388 \n", - " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", - " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", - " temperature kelvin 368.00 368.00 368.00 \n", - " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", - "====================================================================================\n" - ] - } - ], - "source": [ - "m.fs.flash.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Studying Purity as a Function of Heat Duty\n", - "\n", - "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", - "\n", - "First, let's import the matplotlib package for plotting as we did in the previous module.\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to import matplotlib appropriately.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exercise specifications:\n", - "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", - "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "scrolled": true, - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Simulating with Q = -17000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -16142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -15285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -14428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -13571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -12714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -10142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -9285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -8428.57142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -7571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -6714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -4142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -3285.7142857142862\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -2428.5714285714294\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -1571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -714.2857142857156\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 142.8571428571413\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 2714.2857142857138\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 3571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 4428.5714285714275\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 5285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 6142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 8714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 9571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 10428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 11285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 12142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 14714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 15571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 16428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 17285.714285714283\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 18142.857142857145\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 20714.28571428571\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 21571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 22428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 23285.714285714283\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 24142.857142857145\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 25000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Flash Unit Model Tutorial\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "## Key links to documentation\n", + "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" ] - }, - "metadata": { - "filenames": { - "image/png": "C:\\Users\\dkgun\\src\\dangunter\\examples\\idaes_examples\\notebooks\\_build\\jupyter_execute\\docs\\tut\\core\\flash_unit_doc_33_51.png" - } - }, - "output_type": "display_data" - } - ], - "source": [ - "# import the solve_successful checking function from workshop tools\n", - "from idaes_examples.mod.tut.workshoptools import solve_successful\n", - "\n", - "# Todo: import numpy\n", - "import numpy as np\n", - "\n", - "# create the empty lists to store the results that will be plotted\n", - "Q = []\n", - "V = []\n", - "\n", - "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", - "\n", - "# Todo: Write the for loop specification using numpy's linspace\n", - "for duty in np.linspace(-17000, 25000, 50):\n", - " # fix the heat duty\n", - " m.fs.flash.heat_duty.fix(duty)\n", - "\n", - " # append the value of the duty to the Q list\n", - " Q.append(duty)\n", - "\n", - " # print the current simulation\n", - " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", - "\n", - " # Solve the model\n", - " status = solver.solve(m)\n", - "\n", - " # append the value for vapor fraction if the solve was successful\n", - " if solve_successful(status):\n", - " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", - " print(\"... solve successful.\")\n", - " else:\n", - " V.append(0.0)\n", - " print(\"... solve failed.\")\n", - "\n", - "# Create and show the figure\n", - "plt.figure(\"Vapor Fraction\")\n", - "plt.plot(Q, V)\n", - "plt.grid()\n", - "plt.xlabel(\"Heat Duty [J]\")\n", - "plt.ylabel(\"Vapor Fraction [-]\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Repeat the exercise above, but create a figure showing the heat duty vs. the mole fraction of Benzene in the vapor outlet. Remove any unnecessary printing to create cleaner results.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Simulating with Q = -17000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -16142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -15285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -14428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -13571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -12714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -10142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -9285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -8428.57142857143\n" - ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -7571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -6714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -4142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -3285.7142857142862\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -2428.5714285714294\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -1571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -714.2857142857156\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 142.8571428571413\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 2714.2857142857138\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 3571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 4428.5714285714275\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 5285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 6142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 8714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 9571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 10428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 11285.714285714286\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", + "\n", + "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", + "\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to perform the imports. Let a workshop organizer know if you see any errors.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 12142.857142857141\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, + "cell_type": "code", + "source": [ + "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", + "from idaes.core import FlowsheetBlock\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to create the objects\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, + "cell_type": "code", + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: call pprint on the model\n", + "m.pprint()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 2.1 Define Properties\n", + "\n", + "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", + "\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "\n", + "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import and create the properties block.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13857.142857142855\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", + " BTXParameterBlock,\n", + ")" + ], + "outputs": [], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.properties = BTXParameterBlock(\n", + " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", + ")" + ], + "outputs": [], + "execution_count": 7 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 2.2 Adding Flash Unit\n", + "\n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", + "\n", + "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", + "\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "\n", + "Some of the IDAES pre-written unit models:\n", + "* Mixer / Splitter\n", + "* Heater / Cooler\n", + "* Heat Exchangers (simple and 1D discretized)\n", + "* Flash\n", + "* Reactors (kinetic, equilibrium, gibbs, stoichiometric conversion)\n", + "* Pressure changing equipment (compressors, expanders, pumps)\n", + "* Feed and Product (source / sink) components\n", + "\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the Flash and create an instance of the unit model, attaching it to the flowsheet object.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 14714.285714285714\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, + "cell_type": "code", + "source": "from idaes.models.unit_models import Flash", + "outputs": [], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, + "cell_type": "code", + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 15571.428571428569\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 16428.571428571428\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 17285.714285714283\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 4 Set Operating Conditions\n", + "\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 18142.857142857145\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Todo: Call the python help on the degrees_of_freedom function\n", + "help(degrees_of_freedom)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: print the degrees of freedom for your model\n", + "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", + "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", + "\n", + "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", + "\n", + "As an example, to fix the molar flow of the inlet to be 1.0, you can use the following notation:\n", + "```python\n", + "m.fs.flash.inlet.flow_mol.fix(1.0)\n", + "```\n", + "\n", + "To specify variables that are indexed by components, you can use the following notation:\n", + "```python\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", + "```\n", + "\n", + "
\n", + "Note:\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "
\n", + "\n", + "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", + "\n", + "\n", + "To specify the value of a variable on the unit itself, use the following notation.\n", + "\n", + "```python\n", + "m.fs.flash.heat_duty.fix(0)\n", + "```\n", + "\n", + "For this module, we will use the following specifications:\n", + "* inlet overall molar flow = 1.0 (`flow_mol`)\n", + "* inlet temperature = 368 K (`temperature`)\n", + "* inlet pressure = 101325 Pa (`pressure`)\n", + "* inlet mole fraction (benzene) = 0.5 (`mole_frac_comp[0, \"benzene\"]`)\n", + "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", + "* The heat duty on the flash set to 0 (`heat_duty`)\n", + "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19857.142857142855\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: Add inlet specifications given above\n", + "m.fs.flash.inlet.flow_mol.fix(1)\n", + "m.fs.flash.inlet.temperature.fix(368)\n", + "m.fs.flash.inlet.pressure.fix(101325)\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"toluene\"].fix(0.5)\n", + "\n", + "# Todo: Add 2 flash unit specifications given above\n", + "m.fs.flash.heat_duty.fix(0)\n", + "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 20714.28571428571\n" - ] + "metadata": { + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, + "source": [ + "# Todo: print the degrees of freedom for your model\n", + "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 21571.428571428572\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 5 Initializing the Model\n", + "\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", + "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 22428.571428571428\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: initialize the flash unit\n", + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 6 Solving the Model\n", + "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 23285.714285714283\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: create the ipopt solver\n", + "solver = SolverFactory(\"ipopt\")\n", + "\n", + "# Todo: solve the model\n", + "status = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 7 Viewing the Results\n", + "\n", + "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", + "```python\n", + "print('Vap. Outlet Temperature = ', value(m.fs.flash.vap_outlet.temperature[0]))\n", + "```\n", + "\n", + "You can also find more information about a variable or an entire port using the `display` method from Pyomo:\n", + "```python\n", + "m.fs.flash.vap_outlet.temperature.display()\n", + "m.fs.flash.vap_outlet.display()\n", + "```\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cells below to show the current value of the flash vapor outlet pressure. This cell also shows use of the display function to see the values of the variables in the vap_outlet and the liq_outlet.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 24142.857142857145\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, + "cell_type": "code", + "source": [ + "# Print the pressure of the flash vapor outlet\n", + "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", + "\n", + "print()\n", + "print(\"Output from display:\")\n", + "# Call display on vap_outlet and liq_outlet of the flash\n", + "m.fs.flash.vap_outlet.display()\n", + "m.fs.flash.liq_outlet.display()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 25000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, + "cell_type": "code", + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Exercise: Studying Purity as a Function of Heat Duty\n", + "\n", + "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", + "\n", + "First, let's import the matplotlib package for plotting as we did in the previous module.\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to import matplotlib appropriately.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, + "cell_type": "code", + "source": "import matplotlib.pyplot as plt", + "outputs": [], + "execution_count": 42 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Exercise specifications:\n", + "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", + "* Specify the heat duty from -17000 to 25000 over 50 steps\n", + "\n" + ] }, { - "data": { - "image/png": "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", - "text/plain": [ - "
" + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# import the solve_successful checking function from workshop tools\n", + "from idaes_examples.mod.tut.workshoptools import solve_successful\n", + "\n", + "# Todo: import numpy\n", + "import numpy as np\n", + "\n", + "# create the empty lists to store the results that will be plotted\n", + "Q = []\n", + "V = []\n", + "\n", + "# re-initialize model\n", + "FlashInitializer.initialize(m.fs.flash)\n", + "\n", + "# Todo: Write the for loop specification using numpy's linspace\n", + "for duty in np.linspace(-17000, 25000, 50):\n", + " # fix the heat duty\n", + " m.fs.flash.heat_duty.fix(duty)\n", + "\n", + " # append the value of the duty to the Q list\n", + " Q.append(duty)\n", + "\n", + " # print the current simulation\n", + " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", + "\n", + " # Solve the model\n", + " status = solver.solve(m)\n", + "\n", + " # append the value for vapor fraction if the solve was successful\n", + " if solve_successful(status):\n", + " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", + " print(\"... solve successful.\")\n", + " else:\n", + " V.append(0.0)\n", + " print(\"... solve failed.\")\n", + "\n", + "# Create and show the figure\n", + "plt.figure(\"Vapor Fraction\")\n", + "plt.plot(Q, V)\n", + "plt.grid()\n", + "plt.xlabel(\"Heat Duty [J]\")\n", + "plt.ylabel(\"Vapor Fraction [-]\")\n", + "plt.show()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", + "Q = []\n", + "V = []\n", + "\n", + "for duty in np.linspace(-17000, 25000, 50):\n", + " # fix the heat duty\n", + " m.fs.flash.heat_duty.fix(duty)\n", + "\n", + " # append the value of the duty to the Q list\n", + " Q.append(duty)\n", + "\n", + " # print the current simulation\n", + " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", + "\n", + " # solve the model\n", + " status = solver.solve(m)\n", + "\n", + " # append the value for vapor fraction if the solve was successful\n", + " if solve_successful(status):\n", + " V.append(value(m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]))\n", + " print(\"... solve successful.\")\n", + " else:\n", + " V.append(0.0)\n", + " print(\"... solve failed.\")\n", + "\n", + "plt.figure(\"Purity\")\n", + "plt.plot(Q, V)\n", + "plt.grid()\n", + "plt.xlabel(\"Heat Duty [J]\")\n", + "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", + "plt.show()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGwCAYAAABB4NqyAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVp1JREFUeJzt3Qd8zPf/B/BX7rJ3iCwi9iZIZBjV/mqVFq3WHjFiVCdVuigdWjpUq/bee7RUKUVLBolNbGJHkEhk5+7/+Hw0+ScEucjlm7t7PR+Pb+W+980379zXnVc/388w02q1WhARERGZEJXSBRARERGVNAYgIiIiMjkMQERERGRyGICIiIjI5DAAERERkclhACIiIiKTwwBEREREJsdc6QJKI41Gg2vXrsHBwQFmZmZKl0NERESFIKY2TEpKgpeXF1SqJ7fxMAAVQIQfb29vpcsgIiKiIrh8+TIqVKjwxGMYgAogWn5yXkBHR0elyzFZmZmZ2LZtG9q0aQMLCwuly6En4LUyHLxWhoXXSzf37t2TDRg5/44/CQNQAXJue4nwwwCk7Bvf1tZWXgO+8Us3XivDwWtlWHi9iqYw3VfYCZqIiIhMDgMQERERmRwGICIiIjI5DEBERERkchiAiIiIyOQwABEREZHJYQAiIiIik8MARERERCaHAYiIiIhMDgMQERERmRwGICIiIjI5DEBERERkcrgYagm6l5aJe6mZKG2sLdRwtbdSugwiIqISwwBUgpaEX8KkradQGtX1ckSHBp54ub4XKpa1VbocIiIivWIAKkHmKjNYmZe+u44Z2Rocv3ZPbiKgNajghA71PWUgquDCMERERMaHAagEDX6uqtxKm9vJ6fjz+E1sPnoNYedu48iVRLlN/CMGDb2d8XIDT7Sv7wkvZxulSyUiIioWDECEsvZW6BlYUW7xyenYeuwGfj9yDREX7uDQ5QS5fbn5JEKaVsInHWrDQl36WrGIiIh0wQBE+YjO0L2DfOQWl5T2Xxi6jsgLd7Bg30XE3LiHX3v5oYydpdKlEhERFRn/V54ey83BGn2DK2HVkGDM6uMHO0s1ws/fQcdf/sWJa/eULo+IiKjIGICoUNrU9cD64c3gU9YWV+6mosv0ffjj6HWlyyIiIioSBiAqtBruDtg4vBlaVHdFamY2hi2Nxg/bTkGj0SpdGhERkU4YgEgnzraWmB/SBAObV5aPp+48iyFLopCcnqV0aURERIXGAEQ6M1er8NnLdfDdG76wNFdh+4mbeO3Xvbh0+77SpRERERUKAxAV2et+FbBycBDcHKxw+mYyOv6yF/+eiVe6LCIioqdiAKJn0qiiC357u7mcMDExNRP95kdi4b6L0GrZL4iIiEovBiB6Zu6O1lgxOAivNS6PbI0W4zYdx8frjyEjS6N0aURERAViAKJiW1H++zd88XH7WjAzA5ZHxqLP3AjcuZ+hdGlERESPYACiYmNmZibXOpvT1x/2VuZyKY1O0/7F6ZtJSpdGRESUDwMQFbsXa7tj3ZtN4V3GBpfvpOK1X/dhx8mbSpdFRESUiwGI9DhpYnMEVi4j5wgatOgAZu4+x87RRERUKjAAkd6IBVMXDwxEj4CKELln4h8xGLn6MNIys5UujYiITBwDEOmVmCjx61frYXzHulCrzLAu+ip6zg7HraR0pUsjIiITVioC0LRp01CpUiVYW1sjMDAQkZGRjz32+eefl51tH946dOiQe4y4zTJ27Fh4enrCxsYGrVq1wpkzZ0rot6GHievTr2klLOjfBI7W5oiOTUDnaXsRc4MryhMRkYkGoJUrV2LEiBEYN24coqOj4evri7Zt2yIuLq7A49etW4fr16/nbseOHYNarcYbb7yRe8ykSZMwdepUzJgxAxEREbCzs5PnTEtLK8HfjB7Wono5uaJ8ZVc7XE1IRZdf92FnDDtHExFRyTOHwn744QeEhoaif//+8rEILZs3b8a8efMwZsyYR44vU6ZMvscrVqyAra1tbgASrT9TpkzBp59+ik6dOsl9ixYtgru7OzZs2IDu3bs/cs709HS55bh370HLRGZmptyo+FR0tsKq0AC8veIQwi/cxaCFBzCmXU2EBFeULUV55bz2vAalH6+V4eC1Miy8XrrR5XUy0yo4LCcjI0OGlzVr1qBz5865+/v164eEhARs3LjxqeeoX78+goODMWvWLPn4/PnzqFq1Kg4ePIiGDRvmHteyZUv5+KeffnrkHJ9//jnGjx//yP5ly5bJ+qj4iUmi11xQISzuQSNksJsGb1TWQK14myQRERmqlJQU9OzZE4mJiXB0dCy9LUDx8fHIzs6WrTN5iccxMTFP/X7RV0jcAps7d27uvhs3buSe4+Fz5jz3sI8++kjehsvbAuTt7Y02bdo89QWkontFq8WCsFhM3HrqQRCyd8XUbr5wtrXITfLbt29H69atYWHxYB+VTrxWhoPXyrDweukm5w6OQdwCexYi+IgWoICAgGc6j5WVldweJv6y8S+cfg1uWQ1V3RzwzvKDCDt/B11nR2JuP39UKWefewyvg+HgtTIcvFaGhdercHR5jRS94eDq6io7MN+8mb8jrHjs4eHxxO+9f/++7P8zcODAfPtzvq8o5yTlZo5eM6wpyjvb4EL8fbz66z7sOxuvdFlERGTEFA1AlpaW8PPzw44dO3L3aTQa+Vj063mS1atXy47LvXv3zre/cuXKMujkPadoEhOjwZ52TlJObU9HbBjeDI0qOiMxNRN950Vi1YErSpdFRERGSvEup6LvzezZs7Fw4UKcPHkSw4YNk607OaPC+vbtK/voFHT7S3ScLlu2bL79YiTRe++9hy+//BKbNm3C0aNH5Tm8vLzydbSm0qecgxWWhwahU0MvZGm0+GTjCWy6pIJGw+UziIioeCneB6hbt264deuWnLhQdFIWI7W2bt2a24k5NjYWKlX+nHbq1Cn8+++/2LZtW4Hn/PDDD2WIGjx4sBxN1rx5c3lOMdEilW7WFmpM6dYQlcra4acdZ7DjmgrvrDyMKd0bw8ZSrXR5RERkJBQdBl9aiVtmTk5OhRpGR/qz5kAsRq89gmytGXwrOGF2P3+4OTDEltaRKlu2bEH79u3ZUbOU47UyLLxe+vv3W/FbYESP08nXE8PrZMPF1gKHryTi1Wn7uHwGEREVCwYgKtWqOgKrBweiyn/LZ7w+PQy7ThW8TAoREVFhMQBRqedT1hbr3myKoCplkJyehQEL9mNx2EWlyyIiIgPGAEQGwdnWEosGBKJL4woQg8I+23gcE347gWyOECMioiJgACKDYWmuwndvNMCotjXl43l7L2DokiikZGQpXRoRERkYBiAyKGKep+EvVMMvPRvJQLT9xE10nxWOuKQ0pUsjIiIDwgBEBunlBl5YHhooR4gd+W+E2JmbSUqXRUREBoIBiAyWn08ZrH+zGSr/N0LstelcQ4yIiAqHAYgMWiVXO6wb1hT+Pi5ISsuSa4itieIaYkRE9GQMQGTwXOwssWRQIF5u4CnXEPtg9WH8uP00OMk5ERE9DgMQGc0aYlO7N8Kw56vKx2IdsZGrDiMjS6N0aUREVAoxAJHRUKnMMLpdLUx8rT7UKjOsO3gVfedFIDElU+nSiIiolGEAIqPTI6Ai5oU0gb2VOcLP30GXGftw5W6K0mUREVEpwgBERqlljXJYNSQYHo7WOBuXjFd/3YdjVxOVLouIiEoJBiAyWnW8HLF+eFPUdHfAraR0dJvJhVSJiOgBBiAyap5ONlg9LBjNqpXF/YxsDFx4ACv3xypdFhERKYwBiIyeo7UF5ocE4LVG5eXiqaPXHsUPHCZPRGTSGIDIJIh1w77v6ou3XqgmH0/dcQYfrD7CYfJERCaKAYhMaiHVD9rWxNevPhgmvzb6CgYs2I+kNA6TJyIyNQxAZHJ6BlbEnL7+sLVU49+z8XhjRhhuJHI1eSIiU8IARCbphVpuWDk4GK72Voi5kYRXf92L01xNnojIZDAAkcmqX8EJ699siirl7HA9MQ2vT9+HiPO3lS6LiIhKAAMQmTTvMrZYO7Qp/HxccC8tC33mRmLL0etKl0VERHrGAEQmT6wmv3RQINrUcUdGtgbDl0Vj/t4LSpdFRER6xABE9N9q8tN7+6FPkA/E9EDjfzuBiVtOQqPhXEFERMaIAYjoP2Jo/IROdTGqbU35eOae83h/1SHOFUREZIQYgIgemito+AvV8N0bvjBXmWHjoWvovyAS9zhXEBGRUWEAIirA634VMDekiZwraO/Z2+g6Iww373GuICIiY8EARPQYLWuUyzdX0Gu/7sPZuGSlyyIiomLAAERUmLmCXO1wNSEVr8/Yh+jYu0qXRUREz4gBiKgQcwWtHhoMX29nJKRkoufscOyMual0WURE9AzMC3NQ48aNde5IumnTJpQvX76odRGVKmXtrbA8NBBvLo3GrlO3ELooChNfq4+u/t5Kl0ZERPoKQIcOHcLIkSNhb2//1GO1Wi2++eYbpKenF6UeolLL1tIcs/v6Y8zao3Il+Q/XHMGtpHS8+XxVGfqJiMjIApAwatQouLm5FerY77///llqIiq1LNQqfPdGA5RzsMKM3ecw+c9TiLuXhrGv1JXzCBERkRH1Abpw4QLKlStX6JOeOHECPj4+z1IXUaklWnvGvFQLY1+uIx8vDLuEd5YfRHpWttKlERFRcQYgEWZ0aeL39vaGWq0u9PFEhmhA88qY2qMRLNRm2Hz0OvrN44SJREQmMQqsfv36uHz5cvFVQ2RgOvp6YUH/ANhbmSP8/B10mxkub4kREZERB6CLFy8iM5P/x0umrVk1V6wYHCQnTDx5/R66zNiHi/H3lS6LiIiegPMAERWDeuWdsG5YU/iUtcXlOw8mTDx2NVHpsoiISB8BqEWLFrCxsXmWUxAZjYplbbFmaFPU8XREfHIGus8Kx75z8UqXRURExR2AtmzZAk9Pz2c5BZFREcPjVwwJQlCVMkhOz0LIvP344+h1pcsiIqKiBCAxq7MufX1EMEpNTS308UTGxNHaQnaMblfXAxnZGry5LBpLIy4pXRYREekagF599VUkJCSgsLp3747r1/l/vWS6rC3UmNarMXoEVIRWC3yy/him7jgjZ0onIiIDmQlafGiHhITAysqqUCdNS+MwYCIxM/TXr9aDq70lft55Fj9sP43byekY90pdqDhrNBFR6Q9A/fr10+mkvXr1gqOjY1FrIjIaYgLRkW1qoqydJT7/7YScNfr2/Qz80LUhLM05CJOIqFQHoPnz5+u/EiIjFtKsMlzsLPHB6sP4/ch1JKZmYkZvP9hZFXo5PiIiKkb8X1CiEtKpYXnM7dcENhZq/HMmHr3mRODu/QylyyIiMkkMQEQl6Lka5bA0NBBONhY4dDkBXWeG4UYi+8wREZU0BiCiEta4ogtWDw2Gu6MVzsQlo8v0fbjApTOIiEoUAxCRAmq4O8hZoyu72uFqQipen86lM4iIShIDEJFCvMvYypagul6OcmSYWDoj/PxtpcsiIjIJRRqCsmPHDrnFxcVBo9Hke27evHnFVRuR0RMryC8fHITQhQcQceEO+s6LxLSejdG6jrvSpRERGTWdW4DGjx+PNm3ayAAUHx+Pu3fv5tuISPelMxYOCECr2u7IyNJg6JIorIm6onRZRERGTecWoBkzZmDBggXo06ePfioiMtGlM2b0bozRa49ibfQVOV9QQkoGBrWoonRpRERGSecWoIyMDDRt2lQ/1RCZMHO1CpNfb4BBzSvLx19uPonvt53i+mFERKUhAA0aNAjLli3TRy1EJk+sEfZJh9oY1bamfCzWEBu36Tg0GoYgIiJFb4GJhU5nzZqFv/76Cw0aNICFhUW+53/44YfirI/IJNcPG/5CNTjaWGDsxmNYFHYJ91IzMfkNX1ioOXCTiEiRAHTkyBE0bNhQfn3s2LFHPriJqHj0CfKBo7U5Rq46jA2HriEpLQvTejWW/YWIiKiEA9Dff//9jD+SiHRZP8zB2hzDlkRjR0wc+s2LxJx+/nCwzt/ySkREunmm9vQrV67IjYj053+13LFoQAAcrMzlXEE9Z0fgdnK60mUREZlWABITH06YMAFOTk7w8fGRm7OzM7744otHJkUkouIRWKWsnDCxrJ0ljl5NlIuoXktIVbosIiLTCUCffPIJfvnlF3zzzTc4ePCg3L7++mv8/PPP+Oyzz/RTJRGhXnknrBoaDC8na5y7dR9vzAjD+VvJSpdFRGQaAWjhwoWYM2cOhg0bJkeBie3NN9/E7Nmz5QSJRKQ/VcvZY/Wwpqjy3yKqoiXo5PV7SpdFRGT8AejOnTuoVavWI/vFPvEcEelXeWcb2RIkFlGNT85At5lhiI7lMjRERHoNQL6+vvIW2MPEPvEcEZXMIqrLQoPg7+OCe2lZ6D0nAv+eiVe6LCIi4x0GP2nSJHTo0EFOhBgcHCz3hYWF4fLly9iyZYs+aiSiAjjZWGDRwAAMWRyFf87EY8CC/filZyO0qeuhdGlERMbXAtSyZUucPn0ar776KhISEuT22muv4dSpU2jRooV+qiSiAtlamst5gdrV9UBGtgbDlkZj/UFOTUFEpJd5gLy8vPDVV19h7dq1cvvyyy/lvqKYNm0aKlWqBGtrawQGBiIyMvKJx4vANXz4cHh6esLKygo1atTI1/L0+eefyxmp824F9VkiMhZW5mrZ8vO6XwVka7R4f+VhLA67qHRZRESGfwtMLH9Rr149qFQq+fWTiFFhhbVy5UqMGDECM2bMkOFnypQpaNu2rWxNcnNzK3Al+tatW8vn1qxZg/Lly+PSpUtyHqK86tatK2/R5f6S5jrf6SMyuJXkJ3VpAHsrcyzYdxGfbTyOpPQsvPl8NaVLIyIqlQqVDMTaXzdu3JDBQ3wtWlW02kdXpxb7s7OzC/3DxcKpoaGh6N+/v3wsgtDmzZsxb948jBkz5pHjxX4x0mzfvn25i7CK1qNHfilzc3h4sB8Emd5K8uNeqSPXD5u68ywmbT2Fe6lZGN2uJtfpIyIqSgC6cOECypUrl/t1cRCtOVFRUfjoo49y94kWplatWslO1QXZtGmT7HgtboFt3LhR1tSzZ0+MHj0aavX/LxB55swZeUtO3FYTx0+cOBEVK1Z8bC3p6elyy3Hv3oN5VTIzM+VGysh57XkNdPP2C1Vga6nCN1tPY8buc7iXmo5xHWrLgKQvvFaGg9fKsPB66UaX16lQAUgsd5FD3HJq2rTpI7eVsrKyZMtM3mOfJD4+XrYWubu759svHsfExBT4PefPn8fOnTvRq1cv2e/n7NmzchJG8QuPGzdOHiNupYkJGWvWrInr169j/PjxsnO2WLnewcGhwPOKgCSOe9i2bdtga2tbqN+H9Gf79u1Kl2BwPAF0q2KGVedVWBZ5BafPx6JnNQ3Uem4I4rUyHLxWhoXXq3BSUlIKeSRgpi3oXtYTiJYWESwe7qNz+/Ztua+wt8CuXbsm+/CI0JQznF748MMPsXv3bkRERDzyPaLDc1pammyFymnxEbfRJk+eLGt6XKdpEcrEcQMHDix0C5C3t7cMaY6OjoX6faj4iWAr3vSi31fOLU/Sze9HrmPU2mPI0mjRurYbfuzaAFbmz7QGcoF4rQwHr5Vh4fXSjfj329XVFYmJiU/991vn3sEiLxXUn0AEIDs7u0KfRxQoQszNmzfz7RePH9d/R4z8En8B8t7uql27tuyfJG6pWVpaPvI9ooO0CE6itehxxGgysT1M/Cz+hVMer0PRvepXEQ42VnhzWTS2n4zDm8sPY2ZvP9hY/v97qDjxWhkOXivDwutVOLq8RoUOQGKuH0GEn5CQkHyBQbT6iNFh4tZYYYmw4ufnhx07dqBz585yn1hNXjx+6623CvyeZs2aYdmyZfI40V9IEHMSiWBUUPgRkpOTce7cOfTp06fQtREZk1Z13DE/pAkGLTyAPadvod+8SMwN8YeDNT9Mich0Fbot3MnJSW6iBUj0pcl5LDbRYjN48GAsWbJEpx8uhsCLRVTFAqsnT56UC6zev38/d1RY375983WSFs+LUWDvvvuuDD5ixJhYiV50is7xwQcfyFtoFy9elLfXxISNosWoR48eOtVGZEyaVXPFkkEBcLA2R+TFO+g1JwJ372coXRYRkWIK3QI0f/783GHno0aNKpbOwd26dcOtW7cwduxYeRtLDLHfunVrbsfo2NjY3JYeQfTL+fPPP/H+++/L+YZEHyIRhsQosBxXrlyRYUfckhOjxJo3b47w8PDcUWxEpsrPpwyWhwah77xIHLmSiG6zwrBkYCDcHK2VLo2IqMTp3AdItMpcvXoV1atXz7dfDD0X994KmpfnScTtrsfd8tq1a9cj+0SHaRFoHmfFihU6/XwiU1KvvBNWDg5C77kROH0zGV1nhmHJoEBUcOFoRyIyLToPBxH9f8StpYeJUVviOSIq3aq7O2D1kKao4GKDi7dT0HVGGM7fSla6LCKi0h2ADh48KDsjPywoKAiHDh0qrrqISI8qlrXFmqFNUbWcHa4lpqHrzHDE3HgwASgRkSnQOQCJUWBJSUmP7Bdj7nVZBoOIlOXhZI2VQ4JRx9MR8cnp6D4rHEeuJChdFhFR6QxAzz33nJw5OW/YEV+LfaLDMREZDld7K9kxuqG3MxJSMtFrdgQOXLyjdFlERKWvE/S3334rQ5BYakIsMSH8888/cvZFsUwFERkWJ1sL2RF64IL9iLhwB33mRmJOP385dJ6IyFjp3AJUp04dOelh165dERcXJ2+HiZFhYv2uevXq6adKItIreytzLOgfgOdqlENqZjb6L9iPHSfzz9JORGTSLUCCWGldTEBIRMZDLI8xu68f3l52ENtO3MSQxVH4qXsjdGggllYlIjIuRQpAOSuuiokKxRpceYkJConIMFmZqzGtV2N8sPowNh66hreXRyM10xev+1VQujQiImUDkJi5WSxV8ccffxT4PEeCERk2C7UKP3RtCBsLNVbsvyzDkLgt1ifIR+nSiIiU6wP03nvvISEhQU58aGNjI5euEGt5iZmhN23aVHyVEZFi1CozfP1qfYQ0fTCz+2cbjmH2nvNKl0VEpFwLkBjptXHjRvj7+8t1unx8fNC6dWs4OjrKofAdOnQovuqISDEqlRnGvVIHtpZq/LrrHL7achIpGdl458Vqcj4wIiKTagESq7W7ubnJr11cXOQtMaF+/fqIjo4u/gqJSDEi6HzYrhY+aFNDPv7xr9OY9OcpaLVapUsjIirZACTm/zl16pT82tfXFzNnzpSLo86YMQOenhwtQmSM3vpfdXzaobb8evquc5jw+wmGICIyrVtg7777Lq5fvy6/HjduHNq1a4elS5fC0tISCxYs0EeNRFQKDGpRBVYWatkfaP7ei0jL1OCrzvXkrTIiIqMPQL1798792s/PD5cuXZKTIFasWBGurpw5lsiYiZFg1uYqjF57BMsjY5GelY1JXTj1BREZ+S2wzMxMVK1aFSdPnszdZ2tri8aNGzP8EJmIN/y9MaV7IzlSbF30Vby78hAyszVKl0VEpL8WIAsLC6Slpen2E4jI6HT09YKVuQpvLYvG5iPXkZaRhfZOSldFRKTHTtDDhw+XC6JmZWXp+q1EZETa1vXA7L7+MgjtiLmF2TEqpGZwIlQiMtI+QPv378eOHTuwbds2OfTdzs4u3/Pr1q0rzvqIqBR7vqYb5oc0waBFBxCTCIQuica8kADYWRV5lR0iotLZAuTs7IwuXbqgbdu2clFUJyenfBsRmZam1Vwxr29jWKm1iLhwF33mRuBeWqbSZRERPZG5LjNAP/fcc5g/f35hv4WITISfjwuG18nG3LPWiI5NQO85EVg0IADOtpZKl0ZE9GwtQGK5izt37uQ+DgoKkhMgEhEJPvbAov7+KGNniSNXEtFjdgRuJ6crXRYR0bMFoIdnfT1+/DjS0/nhRkT/r46nI1YMDoKrvRVOXr+H7rPCEZfEkaNEZAR9gIiInqSGuwNWDQmCh6M1zsQlo/vMcFxPTFW6LCKiogUgsShi3hWgH35MRJSjSjl7rBoSjPLONjgffx9dZ4bh8p0UpcsiItK9E7S4Bfbiiy/C3PzBt6SkpOCVV16Ra4DlxRXhiUioWNYWq4YGo+fscFy6nYJuM8OwLDQIlVzzT51BRFSqA5BY+DSvTp066aMeIjIiogVItASJEHTu1oOWoGWhgajm5qB0aURk4oocgIiICsPd0RorBgfLofGnbiah28xwLBkUiNqejkqXRkQmjJ2giUjvyjlYYfngINT1csTt+xnoMTscx64mKl0WEZkwBiAiKhFifqBlg4Lg6+2MhJRMeVvs0OUEpcsiIhPFAEREJcbJ1gJLBgbImaPvpWXJ22JRl/5/glUiopLCAEREJcrB2kIukxFYuQyS07PQZ24kws/fVrosIjIxzxSA0tI4wysR6U6sFr+gfwCaV3NFSkY2QuZHYu/ZeKXLIiITonMA0mg0+OKLL1C+fHnY29vj/Pnzcv9nn32GuXPn6qNGIjJCNpZqzOnnj5Y1yiEtU4MBC/Zj16k4pcsiIhOhcwD68ssvsWDBAkyaNCnfJIj16tXDnDlzirs+IjJi1hZqzOrrh1a13ZGepcHgRVH468RNpcsiIhOgcwBatGgRZs2ahV69ekGtVufu9/X1RUxMTHHXR0RGzspcjV97NcZL9TyQka3B0CVR+OPodaXLIiIjp3MAunr1KqpVq1bgrbHMzMziqouITIiluQo/92iEV3y9kKXR4q3lB7Hp8DWlyyIiI6ZzAKpTpw7++eefR/avWbMGjRo1Kq66iMjEmKtVmNKtIV5rXB7ZGi3eW3EQ66KvKF0WEZn6Uhg5xo4di379+smWINHqs27dOpw6dUreGvv999/1UyURmQS1ygzfve4LS7UKK/ZfxsjVh5GVrUXXJt5Kl0ZEpt4CJBZB/e233/DXX3/Bzs5OBqKTJ0/Kfa1bt9ZPlURkMlQqM3z9an30DqoIrRb4cO0RLIuIVbosIjL1FiChRYsW2L59e/FXQ0T0Xwj6olM9mKtUWLDvIj5efxRZGg36BldSujQiMhKcCZqISiUzMzOMe6UOQltUlo/HbjyOOf88mHeMiKhEWoBcXFzkh1Fh3LnDdX2IqHiIz52P29eGhVqFX3edw5ebT8pRYkNbVlW6NCIyhQA0ZcoU/VdCRPSYEDSqbU0Zgn7acQbf/BGDrGwN3vpfdaVLIyJjD0Bi1BcRkZIh6P3WNWCuMsP320/ju22nkZmtxXutqhe6dZqI6Jk7QWdnZ2PDhg1y9JdQt25ddOzYMd/M0ERExe3tF6vDwlwlW4FEa1Bmtka2DjEEEZHeA9DZs2fRvn17OQ9QzZo15b6JEyfC29sbmzdvRtWqvDdPRPoj+v+IliDRH0j0CxJ9gj56qRZDEBHpdxTYO++8I0PO5cuXER0dLbfY2FhUrlxZPkdEpG+DWlTB+I515dez9pzHF7+fhFZMGkREpK8WoN27dyM8PBxlypTJ3Ve2bFl88803aNasma6nIyIqkn5NK8FcbYZP1h/DvL0XkK3R4POOddkSRET6aQGysrJCUlLSI/uTk5NhaWmp6+mIiIqsV6APvu1SHyLzLAy7hE83HINGw5YgItJDAHr55ZcxePBgREREyCZnsYkWoaFDh8qO0EREJalbk4qY/LqvDEFLI2LlrNEMQURU7AFo6tSpsg9QcHAwrK2t5SZufVWrVg0//fSTrqcjInpmr/tVwI9dG0JlBrmI6qg1R+SK8kRExdYHyNnZGRs3bsSZM2cQExMj99WuXVsGICIipXRuVF6uJv/eykNYG31F9gn67g1fmKu54g8RFdM8QEL16tXlRkRUWrzi6yVD0DvLD2LDoWvI1gI/dmUIIqJnCEATJkwo1HFjx44t7CmJiIpd+/qeMgS9tSwavx2+JpfNmNqjkVxKg4hI5wD0+eefw8vLC25ubo+db0MMP2UAIiKlta3rgRm9/TBsSTT+OHYDw5dG45eejWFpzhBERDoGoJdeegk7d+6Ev78/BgwYIEeDqVT8MCGi0unF2u6Y2dcPQxZHYduJm3hzaRSm9WoMK3Mu2UNEOowCE8tcnDt3DoGBgRg1ahTKly+P0aNH49SpU/qtkIioiF6o6YY5ff1hZa7CXyfjMHRxFNIys5Uui4hKAZ2acMQtsI8++kiGnpUrVyIuLg5NmjSRw+BTU1P1VyURURE9V6Mc5oU0gbWFCn+fuiVbhBiCiKjI97BE8HnhhRfkEPiDBw8iMzOzeCsjIiomzaq5yhBkY6HG7tO3ELroAFIzGIKITJnOASgsLAyhoaHw8PDAzz//jH79+uHatWtwdHTUT4VERMWgaVVXLOjfBLaWavxzJh4DF+5HSkaW0mURUWkPQJMmTUKdOnXQqVMn2Nvb459//sH+/fvx5ptvyskRiYhKu8AqZbFoQADsLNXYd+42+s/fj/vpDEFEpqjQo8DGjBmDihUromvXrnK4+4IFCwo87ocffijO+oiIipV/pTJYNDAQIfMiEXHhDkLmR2J+/wDYWxV5XlgiMkCFfsc/99xzMvgcP378sceI54mISjs/HxcsHhSIPnMjsP/iXfSdG4GFAwLgYG2hdGlEVNoC0K5du/RbCRFRCWro7Yxlg4LQe24EomMT0GduJBYNDIAjQxCRSeBMhkRksupXcMLSQYFwtrXAocsJ6DMnAompHNFKZAoYgIjIpNUr7yRbglxsLXD4SiJ6z4lAQkqG0mURkZ4xABGRyavj5Yjlg4NQ1s4SR68motecCNy9zxBEZMwUD0DTpk1DpUqVYG1tLZfZiIyMfOLxCQkJGD58ODw9PWFlZYUaNWpgy5Ytz3ROIqJaHg9CkKu9JY5fu4eecyJwhyGIyGgpGoDEchojRozAuHHjEB0dDV9fX7Rt21YusVGQjIwMtG7dGhcvXsSaNWvkkhyzZ8+W65IV9ZxERDlquDtgeagIQVY4ef0ees4Ox+3kdKXLIqLSEoDEJIi9e/dGcHAwrl69KvctXrwY//77r07nEXMGiVml+/fvLydZnDFjBmxtbTFv3rwCjxf779y5gw0bNsj1x0QrT8uWLWXIKeo5iYjyqu7ugBWDg+DmYIWYG0noMTsct5IYgoiMjc4zf61duxZ9+vRBr1695Bpg6ekPPhgSExPx9ddfP3I76nFEa05UVJRcXDWHSqVCq1at5HIbBdm0aZMMXeIW2MaNG1GuXDn07NlTrkqvVquLdE5B/A45v4dw7949+adY34xrnCkn57XnNSj9jO1a+bhYYckAf/SZdwCnbyaj+6wwLO7vj3IOVjB0xnatjB2vl250eZ10DkBffvmlbFXp27cvVqxYkbtftMiI5worPj4e2dnZcHd3z7dfPI6JiSnwe86fP4+dO3fK8CWC1tmzZ+VSHOIXFre8inJOYeLEiRg/fvwj+7dt2yZbj0hZ27dvV7oEMtFrFVoV+OWEGudu3UfnqbvwVt1sOFnCKBjbtTJ2vF6Fk5KSor8AJPrdiFmhH+bk5CQ7KOuTRqOBm5sbZs2aJVt8/Pz85C24yZMnywBUVKLFSPQbytsC5O3tjTZt2nCRVwWJYCve9KLfl4UFJ6crzYz5Wr3wQopsCbqWmIZ5Fx2xeIA/PBytYaiM+VoZI14v3eTcwdFLABKrwIuWF9H/Ji/R/6dKlSqFPo+rq6sMMTdv3sy3XzwWP6MgYuSX+Asgvi9H7dq1cePGDXn7qyjnFMRoMrE9TPws/oVTHq+D4TDGa1XV3QkrhwSj+6xwXLz9IAyJ0WKeTjYwZMZ4rYwZr1fh6PIa6dwJWnQwfvfddxERESHX/rp27RqWLl2KDz74AMOGDSv0eSwtLWULzo4dO/K18IjHop9PQcRtNhG+xHE5Tp8+LYOROF9RzklE9DTeZWyxckgQvMvYyBDUbWY4riakKl0WET0DnQOQWBVedDx+8cUXkZycLG+HDRo0CEOGDMHbb7+t07nEbScxjH3hwoU4efKkDFD379+XI7gE0c8ob4dm8bwYBSYCmAg+mzdvlh2vRafowp6TiKgoKrjYYsXgYFQsY4vYOymyY/SVu4Xvb0BEpYvOt8BEq88nn3yCUaNGydYYEYLEcHN7e3udf3i3bt1w69YtjB07Vt7GatiwIbZu3ZrbiTk2NlaO4soh+uX8+eefeP/999GgQQM5/48IQ2IUWGHPSURUVOWdbWRLUI//boeJliAxZF60EBGRYTHTarVapYsojZ2oRKduMbSfnaCV7fwnRvu1b9+e975LOVO7VjcS0+Qkiefj78PLyVr2CfIpawdDYGrXytDxeunv32+db4GJ20mfffYZmjZtimrVqsmOz3k3IiJj5+FkLVt+qpSzk6PDZAfp+PtKl0VE+rwFJvr77N69W06GKDofi1tiRESmxs3xQQjqOTsCZ+OS0W1WmFxGo0o53bsDEJEBBKA//vhDdj4WI7KIiEyZm4O1DD295oT/N2N0OJaFBqGaG0MQUWmn8y0wFxcXlClTRj/VEBEZGLE8hgg9tTwcEJeULkPQ2bgkpcsiouIOQF988YUcYaXLdNNERMZMrB6fE4Likx+EoNM3GYKIjOoW2Pfff49z587JYeViNuiHe6VHR0cXZ31ERAahjJ3lf7fDInDi+j05VH5paCBqeXAkKZFRBKDOnTvrpxIiIgPnYmeJZaGB6D03Aseu3pMdpJcMDEQdL4YgIoMPQM+y6CgRkbFztrXE0oFB6DMvAkeuJKLnnHAsHRSIul5OSpdGRM/SB0gQq77PmTNHLlMhlqbIufUlVmYnIjJ1TrYWWDwwEL7ezkhIyZQtQceuJipdFhE9SwA6cuQIatSogW+//RbfffedDEPCunXr8q3bRURkypxsRAgKQKOKzkhMFSEoHEeuPPi8JCIDDEBisdGQkBCcOXMG1tbWufvFNN179uwp7vqIiAyWo7UFFg0IgJ+PC+6lZckO0ocuMwQRGWQA2r9/v1z5/WFiYVKx+CgREf0/B2sLLBwQgCaVXJCUloU+cyIQHXtX6bKITJ7OAcjKykouNvaw06dPo1y5csVVFxGR0bC3MseC/gEIqFwGSelZ6Ds3ElGXHvSfJCIDCUAdO3bEhAkT5Aq1glgLLDY2FqNHj0aXLl30USMRkcGzkyGoCYKqlEHyfyFo/0WGICKDCUBiIsTk5GS4ubkhNTUVLVu2lKvCOzg44KuvvtJPlURERsDW0hzzQwLQtGpZ3M/IRr95kYg4f1vpsohMks7zADk5OWH79u34999/5YgwEYYaN26MVq1a6adCIiIjYmOpxtx+TRC66AD+PRuPkPn7MV+2DJVVujQik6JzABK3u8QyGM2bN5dbDq1Wi8uXL6NixYrFXSMRkdGFoDn9/GUI+udMPPrP34+5If5oWtVV6dKITIbOt8DE+l+ixUesB5ZXXFwcKleuXJy1EREZLWsLNWb39cfzNcshNTMbAxbsx96z8UqXRWQyijQTdO3atREQEIAdO3bk2y9agYiIqPAhaGYfP/yvlhvSMjUyBO05fUvpsohMgs4BSIz6+vXXX/Hpp5+iQ4cOmDp1ar7niIio8KzM1ZjeuzFa1XZHepYGgxYdwK5TcUqXRWT0dA5AOa0877//PtavX4+xY8ciNDQUGRkZ+qiPiMgkQtCvvRqjbV13ZGRpMHhRFP6OYQgiKnW3wHK89NJL2LdvH/7++2+8/PLLxVcVEZGJsTRX4ZeejfFSPQ9kZGswZHEU/jpxU+myiIyWzgFIzPtjaWmZ+7hOnToIDw+Hs7Mz+wARET0DC7UKU3s0QocGnjIEDVsahW3HucQQUakIQKK1R4SdvFxdXbF7925oNJrirI2IyCRD0E/dGuIVXy9kZmvx5tJobD12XemyiIyOzvMACSLonD17Vg59zxt6RCfoFi1aFGd9REQmx1ytwo9dfaE2AzYcuobhyw5ianfIliEiUigAidtdPXv2xKVLlx655SUCUHZ2djGVRkRk2iHo+64NoVKZYV30Vbyz4iA0Wq1sGSIiBQLQ0KFD4e/vj82bN8PT05ND34mI9EStMsPk132hMjPDmqgrePe/ENSpYXmlSyMyvQB05swZrFmzRi6ASkRE+g9Bk7o0gNrMDCsPXMb7Kw8hW6PFa40rKF0akWl1gg4MDJT9f4iIqGSI22ATX6uPHgEVodECI1cfxuoDl5Uui8i0WoDefvttjBw5Ejdu3ED9+vVhYWGR7/kGDRoUZ31ERPRfCPqqcz2oVcCS8Fh8uPaIvB3WrQkXoCYqkQDUpUsX+eeAAQNy94l+QKJDNDtBExHpNwR90amevB22MOwSRq89imwN0DOQIYhI7wHowoULOv8QIiIqHuJ/ND/vWBdqlQrz9l7Ax+tFCNKgT3AlpUsjMu4A5OPjo59KiIio0CHos5dry9ths/+5gM82HkeWRov+zSorXRqRca8FtnjxYjRr1gxeXl5yPiBhypQp2LhxY3HXR0REjwlBH7evjSEtq8jH4387gTn/nFe6LCLjDUDTp0/HiBEj0L59eyQkJOT2+RHLY4gQREREJReCxrSrheEvVJWPv9x8ErP2nFO6LCLjDEA///wzZs+ejU8++QRqtTp3v5gc8ejRo8VdHxERPSUEfdCmJt55sbp8/PWWGPy6i1OVEBV7ABKdoBs1avTIfisrK9y/f1/X0xERUTGEoBGta+D9VjXk40lbT+HnHWeULovIuAJQ5cqVcejQoUf2b926FbVr1y6uuoiISEfvtqqOUW1ryq+/334aP24//ciajURUxFFgov/P8OHDkZaWJt9YkZGRWL58OSZOnIg5c+boejoiIipGw1+oJpfP+OaPGPy044ycLFG0DnHdRqJnDECDBg2CjY0NPv30U6SkpMiV4cVosJ9++gndu3fX9XRERFTMhrasCnOVmewU/fPOs8jM1mJ0u5oMQUTPEoCEXr16yU0EoOTkZLi5uRXlNEREpCeDWlSRq8hP+P0EZuw+JydLFMPmiegZAlAOW1tbmJubyxBkb2//LKciIqJiNqB5ZZirzTB243E5YaKYLPGjtg9GixGZOp06Qc+fP18uhrp06VL5+KOPPoKDgwOcnJzQunVr3L59W191EhFREfQNroSvX60vv56/9yImbI6RK8oTmbpCB6CvvvpKdn6OiYnBO++8g2HDhmHBggWYMGECvvnmG7lf9AsiIqLSRSyWOqlLA4guQEsiLmP1BRU0TEFk4gp9C0yEnblz56JHjx44cOAAAgMDsWrVqtzV4evVq4ehQ4fqs1YiIiqirk285Wryo9Ycxr6bKny66QS+7eIr9xGZokK3AMXGxqJ58+a5sz6Lvj8i9ORo0KABrl+/rp8qiYjomb3uVwHfdakPM2ixOuoqRq05gmy2BJGJKnQAyszMlLM957C0tISFhUXuYxGIctYFIyKi0qmjryf6VtfIuYLWRl/ByFWHkJWtUbosotI9CuzEiRO4ceOG/FpMgij6/YgRYEJ8fLx+KiQiomLV2FULf78GeH/VEWw4dA3ZWuDHrr4wV+u8OACRaQSgF198Md+06i+//LL8U0yuJfZzki0iIsPQrq47rHo1xvBl0fjt8DU5T9BP3RvBgiGITIS5LougEhGR8WhT1wMzevth2JJobDl6A1nZ0filZ2NYmjMEkfErdADy8fHRbyVERFTiXqztjll9/TB4cRS2nbiJoUui8GuvxrC2UCtdGpFeMeYTEZm452u6YV6/JrC2UGFnTJwMQ2mZHNRCxo0BiIiI0Ly6K+aHBMDGQo09p29h4ML9SM1gCCLjxQBERERScNWyWDggAHaWauw9exsh8yNxPz1L6bKIlA9AYqSXmBAxLS1NP9UQEZGiAiqXwaKBgXCwMkfEhTvoNy8SSWmZSpdFpHwAqlatGi5fvlz8lRARUang5+OCxYMC4WhtjgOX7qLvvEgkpjIEkQkHIJVKherVq3PVdyIiI9fQ2xnLQoPgbGuBg7EJ6DM3AgkpGUqXRaRcHyCx8vuoUaNw7Nix4quCiIhKnXrlnbBsUBDK2FniyJVE9JwdgTv3GYLIOOgcgPr27YvIyEj4+vrCxsYGZcqUybcREZHxqOPliOWhQXC1t8SJ6/fQc3Y44pPTlS6LqGSXwhCmTJny7D+ViIgMRk0PB6wYHCzDT8yNJHSfFY5lgwLh5mitdGlEJReA+vXrV/SfRkREBqmamz1WDnkQgs7GJaObCEGhgfB0slG6NKKSCUBCdnY2NmzYgJMnT8rHdevWRceOHaFWc+p0IiJjVdnVDquGBMsWoAvx99Ft5oMQVMHFVunSiPTfB+js2bOoXbu27Au0bt06ufXu3VuGoHPnzuleARERGQzvMrZYNTQYFcvYIvZOigxBsbdTlC6LSP8B6J133kHVqlXlXEDR0dFyE5MjVq5cWT5HRETGrbyzjWwJquJqh6sJqeg6MwznbyUrXRaRfgPQ7t27MWnSpHwjvsqWLSuHx4vniIjI+Hk4WWPFkCBUd7PHjXtpsk/Q2bgkpcsi0l8AsrKyQlLSo3/Jk5OTYWlpqevpiIjIQLk5WGP54CDU8nDAraR0eTss5sY9pcsi0k8AevnllzF48GBERETIpTHEFh4ejqFDh8qO0EREZDpc7a3kPEH1yjvi9v0M9JgVjmNXE5Uui6j4A9DUqVNlH6Dg4GBYW1vLrVmzZnKNsJ9++knX0xERkYFzsbPE0kFB8PV2xt2UTDlU/tDlBKXLIireAOTs7IyNGzfi1KlTWL16NdasWSO/Xr9+PZycnFAU06ZNQ6VKlWSYCgwMlDNNP86CBQtgZmaWbxPfl1dISMgjx7Rr165ItRER0dM52VhgycAA+Pu44F5aFnrPicCBi3eULouoeOcBEsSiqKLVRxABo6hWrlyJESNGYMaMGTL8iJmm27ZtK0OVm5tbgd/j6Ogon89R0M8XgWf+/Pn5+i4REZH+OFhbYOGAAAxcuB/h5+/IVeTn9muC4KpllS6NqHgC0Ny5c/Hjjz/izJkzuWHovffew6BBg3Q+1w8//IDQ0FD0799fPhZBaPPmzZg3bx7GjBlT4PeIwOPh4fHE84rA87RjcqSnp8stx717DzrxZWZmyo2UkfPa8xqUfrxWhkPf18pSBczq1QjDlh3C3nO3ETI/EtN7NUSLaq56+XnGju8t3ejyOukcgMaOHStDy9tvvy37AQlhYWF4//335XxAEyZMKPS5MjIyEBUVhY8++ih3n0qlQqtWreQ5H0eMOPPx8YFGo0Hjxo3x9ddfy4kY89q1a5dsQXJxccH//vc/fPnll3K4fkEmTpyI8ePHP7J/27ZtsLXlDKdK2759u9IlUCHxWhkOfV+rV12Bu7dVOJEAhC6KwoCaGtRz0er1ZxozvrcKJyWl8JNymmnFMC4dlCtXTnaE7tGjR779y5cvl6EoPj6+0Oe6du0aypcvj3379uWGKeHDDz+UcwqJkWYPE8FItDw1aNAAiYmJ+O6777Bnzx4cP34cFSpUkMesWLFCBhcxOaOYnfrjjz+Gvb29/N6ClusoqAXI29tb/i7idhspl+TFm75169awsLBQuhx6Al4rw1GS1yojS4P3Vh3B9pNxsFCb4cc3GqBtXXe9/kxjw/eWbsS/366urjIfPO3fb/OiXAx/f/9H9vv5+SErKwv6JoJS3rDUtGlTuTTHzJkz8cUXX8h93bt3z32+fv36MiyJkWuiVejFF18s8HZZQX2ExF82/oVTHq+D4eC1Mhwlca3E6X/t7YcRqw7jt8PX8O6qI/ixW0N09PXS6881RnxvFY4ur5HOo8D69OmD6dOnP7J/1qxZ6NWrl07nEilNtMjcvHkz337xuLD9d8Qv26hRI7lG2eNUqVJF/qwnHUNERMXPQq3ClG4N8Vrj8sjWaPHeioNYE3VF6bKIit4JWvSPCQoKko/FrSrR/0cskCpGdOUQfYWeRMwcLVqOduzYgc6dO8t9ol+PePzWW28VemX6o0ePon379o895sqVK7h9+zY8PT0L+RsSEVFxUavM8N3rvrBUq7Bi/2V8sPqwvD3WM7Ci0qWRCdM5AB07dkx2PBZyVn8XrStiE8/lKOzQeBGY+vXrJ2+rBQQEyGHw9+/fzx0VJkKV6CckOioLopO1CF5iCH5CQgImT56MS5cu5Y5AEx2kRYfmLl26yFYkUaPoUySOF8PriYio5KlUZvj61fqwMldhYdglfLz+KDKyshHSrLLSpZGJ0jkA/f3338VaQLdu3XDr1i05uuzGjRto2LAhtm7dCnf3Bx3lRMuSGBmW4+7du3LYvDhWjPASLUiiE3WdOnXk8+KW2pEjR7Bw4UIZkLy8vNCmTRvZP4hzARERKRuCPu9YF1YWaszacx6f/3YCaVkaDG1ZVenSyAQVeSLE4iRudz3ulpfouJyXmH9IbI9jY2ODP//8s9hrJCKiZyfuDnz0Ui1Ym6swdedZfPNHDNIys/Hui9WfaVJdohIJQAcOHMCqVatk64yYyyevdevWFeWURERkIkTQGdGmpmwJmvznKUz56wzSMjUY3a4mQxCVGJ1HgYk5dsTQ85MnT8r1v8SweDEHz86dO4u8FhgREZme4S9Uw2cvP+i+MGP3OYz/7QR0nJqOqOQCkJh1WdyC+u233+QoLrECfExMDLp27YqKFdmjn4iICm9g88r4snM9+fWCfRfx8fpj0GgYgqgUBiAxqqpDhw7yaxGAxIgt0WQplsIQcwERERHponeQDya/3gAqM2B5ZCw+WHMYWdkapcsiI6dzABIjr5KSkuTXYnh6ztB3MeJKlzU4iIiIcrzh740p3RvJOYPWRV/FuysPIZMhiEpTJ+jnnntOrksilph444038O6778r+P2JfQctMEBERFYZYIkNMlvj28mhsPnJdTpb4S89GsDJ/dA1HohJrAcpp6fnll19y19r65JNP5ESGYukKMfGgmCGaiIioqNrV88Csvv5ywsTtJ27KleRTM7KVLotMOQCJBUUDAwOxdu1aODg4PPhmlQpjxozBpk2b8P3338vbY0RERM/ihZpumB/SBLaWauw5fQsh8yORnK7/xbbJtBQ6AO3evRt169bFyJEj5ZpaYvmKf/75R7/VERGRSWpazRWLBwbAwcocERfuoM/cCCSmZipdFpliAGrRogXmzZuH69ev4+eff8bFixfRsmVL1KhRA99++61cmoKIiKi4+PmUwbLQIDjbWuBgbAJ6zg7Hnfv5J98lKrFRYHZ2dnKhUtEidPr0adkRetq0aXIOoI4dOxa5ECIioofVr+CEFYOD4GpviePX7qHbzDDE3UtTuiwyxQCUl1hh/eOPP8ann34q+wVt3ry5+CojIiICUMvDESuHBMPD0Rpn4pLRdWYYriakKl0WmWoA2rNnD0JCQuDh4YFRo0bhtddew969e4u3OiIiIgBVy9lj9dBgVHCxwcXbKeg6IwyXbt9XuiwylQB07do1uRSG6Pfz/PPP4+zZs5g6darcP3v2bAQFBemvUiIiMmneZWxlCKriaidbgN6YEYazcQ8m5iXSWwB66aWX4OPjIztAv/rqq3Ix1H///Vf2BxL9goiIiPTN08lG3g6r6e6AuKR0dJsZjuPXEpUui4w5AFlYWGDNmjW4cuWKHPVVs2ZN/VZGRERUgHIOVrJjdP3yTrh9PwM9ZoUjOvau0mWRsQYgMdlhp06doFZzSnIiIlKWi50lloYGwt/HBffSstB7TgTCzt1WuiwylVFgRERESnG0tsCigQFoXs0VKRnZcsbov2PilC6LDAQDEBERGSxbS3PM6eePVrXdkJ6lweDFB/DH0etKl0UGgAGIiIgMmrWFGtN7++HlBp7IzNZi+LJorI26onRZVMoxABERkcGzUKvwU/dG6OpfARotMHL1YSwJv6R0WVSKMQAREZFRUKvM8M1rDRDStJJ8/OmGY5i155zSZVEpxQBERERGQ6Uyw7hX6uDN56vKx19vicEP209Dq9UqXRqVMgxARERkVMzMzPBhu1oY1fbBfHVTd5zBV5tPMgRRPgxARERklIa/UE22Bglz/r2Aj9YdRbboIETEAERERMasf7PKmNSlAVRmwIr9l/HeykPIzNYoXRaVAgxARERk1Lo28cbUHo1grjLDb4evYdiSKKRlZitdFimMAYiIiIzeyw28MLuvP6zMVfjrZBwGLNiP++lZSpdFCmIAIiIik/BCLTcsHBAAO0s19p27jd5zI5CYkql0WaQQBiAiIjIZQVXKYmloEJxsLHAwNgHdZ4cjPjld6bJIAQxARERkUhp6O2PlkCC42lvh5PV76DojDNcSUpUui0oYAxAREZmcWh6OWD00GOWdbXA+/j7emBGGi/H3lS6LShADEBERmaTKrnZYNTRY/nk1IRWvzwhDzI17SpdFJYQBiIiITJZoAVo1JBi1PR1lX6BuM8MRHXtX6bKoBDAAERGRSSvnYIUVoUFoXNEZiamZ6D0nAnvPxitdFukZAxAREZk8J1sLLB4YiObVXJGSkY3+8/dj2/EbSpdFesQAREREBMDOyhxzQ/zRtq47MrI1GLY0GusPXlG6LNITBiAiIqL/WJmrMa1nY3RpXEEunPr+ysNYHHZR6bJIDxiAiIiI8jBXqzD59QYIaVpJPv5s43FM+/sstFquJG9MGICIiIgeolKZYdwrdfDOi9Xl48l/nsI3W2MYgowIAxAREVEBzMzMMKJ1DXzaobZ8PHP3eXy8/pi8NUaGjwGIiIjoCQa1qIJvu9SHygxYHhmLd1YcREaWRumy6BkxABERET1FtyYV8UvPxrBQm2HzkesYtOgAUjKylC6LngEDEBERUSG0r++Juf2awMZCjT2nb6HP3EgkpmQqXRYVEQMQERFRIT1XoxyWDAqEo7U5oi7dRbdZYYhLSlO6LCoCBiAiIiId+Pm4yEVUxRIaMTeS5Eryl++kKF0W6YgBiIiISEe1PByxZmgwvMvY4NLtFLw+Yx9O30xSuizSAQMQERFREfiUtcOaoU1Rw90eN++lo+vMMBy6nKB0WVRIDEBERERF5O5ojZWDg+Hr7YyElEz0nB3OleQNBAMQERHRM3Cxs8SyQYFoVq1s7kryW49dV7osegoGICIiomJYSX5eSBO0q+shV5J/c2k0VkTGKl0WPQEDEBERUXGtJN+rMbo38YZYLWPMuqOYsfuc0mXRYzAAERERFRO1ygwTX6uPYc9XlY+/+SMGE7ec5CKqpRADEBERUTEvojq6XS183L6WfDxzz3mMXnsEWdlcP6w0YQAiIiLSg8HPVcWk1xvIRVRXHbgi+wWlZWYrXRb9hwGIiIhIT7r6e2N6bz9Ymquw7cRNOUIsKY3rh5UGDEBERER61LauBxb2D4C9lTnCzt9Gj9nhiE9OV7osk8cAREREpGfBVctixeAglLWzxLGr99B1Rhiu3OX6YUpiACIiIioB9co7YfXQYJR3tsH5+PvoMp3rhymJAYiIiKiEVClnj7XD/n/9MLGSfNSlO0qXZZIYgIiIiEqQh5M1Vg0Jhp+PCxJTM9FrTgR2xtxUuiyTwwBERERUwpxtLbFkYCD+V8sNaZkahC6KwtqoK0qXZVIYgIiIiBRgY6nGzD5+eK1ReWRrtBi5+jBm7zmvdFkmgwGIiIhIIRZqFb57wxeDmleWj7/achIT/+DSGSWBAYiIiEhBKpUZPulQG2Ne+m/pjN3n8eEaLp2hbwxAREREpWD9sKEt/3/pjNVRVzBkcRRu3ktTujSjZa50AURERPT/S2e42FrirWXR2BEThz1nbqGJqwr176agipuT0uUZlVLRAjRt2jRUqlQJ1tbWCAwMRGRk5GOPXbBggUzKeTfxfXmJe6djx46Fp6cnbGxs0KpVK5w5c6YEfhMiIqJn07qOu5w1OqBSGWRma7Hvpgqtp+zFiFWHcDYuWenyjIbiAWjlypUYMWIExo0bh+joaPj6+qJt27aIi4t77Pc4Ojri+vXrudulS5fyPT9p0iRMnToVM2bMQEREBOzs7OQ509LYlEhERKVfo4ouWDU0GEsH+qOWk0aOElsXfRWtf9yNN5dG4fi1RKVLNHiK3wL74YcfEBoaiv79+8vHIrRs3rwZ8+bNw5gxYwr8HtHq4+HhUeBzovVnypQp+PTTT9GpUye5b9GiRXB3d8eGDRvQvXt3Pf42RERExUe0Ag2ro0GFBsGY+c9FuaL8lqM35PZCzXIY0rIqKrjYwBA5WFnAydbCNANQRkYGoqKi8NFHH+XuU6lU8pZVWFjYY78vOTkZPj4+0Gg0aNy4Mb7++mvUrVtXPnfhwgXcuHFDniOHk5OTvLUmzllQAEpPT5dbjnv37sk/MzMz5UbKyHnteQ1KP14rw8FrZVhyrlNtd1tM6+Er1w6bvvsCthy7gb9P3ZKboRr6XGWMbF29WM+py99rRQNQfHw8srOzZetMXuJxTExMgd9Ts2ZN2TrUoEEDJCYm4rvvvkPTpk1x/PhxVKhQQYafnHM8fM6c5x42ceJEjB8//pH927Ztg62t7TP8hlQctm/frnQJVEi8VoaD18pwr1dre8DXF9hxTYVDt81gqKPlL5w7hy2Zxds/NyUlxXBugekqODhYbjlE+KlduzZmzpyJL774okjnFC1Qoh9S3hYgb29vtGnTRvY3ImWIJC/e9K1bt4aFhXLNpPR0vFaGg9fKeK5XiGJVlV45d3BKfQBydXWFWq3GzZv5F4ETjx/Xx+dh4i9Eo0aNcPbsWfk45/vEOcQosLznbNiwYYHnsLKykltB5+YHhPJ4HQwHr5Xh4LUyLLxehaPLa6ToKDBLS0v4+flhx44duftEvx7xOG8rz5OIW2hHjx7NDTuVK1eWISjvOUUiFKPBCntOIiIiMm6K3wITt5769esHf39/BAQEyBFc9+/fzx0V1rdvX5QvX1720xEmTJiAoKAgVKtWDQkJCZg8ebIcBj9o0KDcEWLvvfcevvzyS1SvXl0Gos8++wxeXl7o3Lmzor8rERERlQ6KB6Bu3brh1q1bcuJC0UlZ3KbaunVrbifm2NhYOTIsx927d+WweXGsi4uLbEHat28f6tSpk3vMhx9+KEPU4MGDZUhq3ry5POfDEyYSERGRaTLTcsnZR4hbZmLovBhlxk7Qynb+27JlC9q3b89736Ucr5Xh4LUyLLxe+vv3W/GZoImIiIhKGgMQERERmRwGICIiIjI5DEBERERkchiAiIiIyOQwABEREZHJYQAiIiIik8MARERERCaHAYiIiIhMjuJLYZRGOZNjixklSdkZUFNSUuR14AyopRuvleHgtTIsvF66yfl3uzCLXDAAFSApKUn+6e3trXQpREREVIR/x8WSGE/CtcAKoNFocO3aNTg4OMjV5Um5JC9C6OXLl7kmWynHa2U4eK0MC6+XbkSkEeHHy8sr30LqBWELUAHEi1ahQgWly6D/iDc93/iGgdfKcPBaGRZer8J7WstPDnaCJiIiIpPDAEREREQmhwGISi0rKyuMGzdO/kmlG6+V4eC1Miy8XvrDTtBERERkctgCRERERCaHAYiIiIhMDgMQERERmRwGICIiIjI5DECkV1999RWaNm0KW1tbODs7F3hMbGwsOnToII9xc3PDqFGjkJWVle+YXbt2oXHjxnIkRLVq1bBgwYJHzjNt2jRUqlQJ1tbWCAwMRGRkZL7n09LSMHz4cJQtWxb29vbo0qULbt68Wcy/sWl62mtPz2bPnj145ZVX5Oy2Ynb6DRs25HtejGUZO3YsPD09YWNjg1atWuHMmTP5jrlz5w569eolJ9MT78WBAwciOTk53zFHjhxBixYt5HUUsw9PmjTpkVpWr16NWrVqyWPq16+PLVu26Om3NkwTJ05EkyZN5EoC4vOsc+fOOHXqlM6fRSX1uWjSxCgwIn0ZO3as9ocfftCOGDFC6+Tk9MjzWVlZ2nr16mlbtWqlPXjwoHbLli1aV1dX7UcffZR7zPnz57W2trbyHCdOnND+/PPPWrVard26dWvuMStWrNBaWlpq582bpz1+/Lg2NDRU6+zsrL1582buMUOHDtV6e3trd+zYoT1w4IA2KChI27Rp0xJ4FYxbYV57ejbiffHJJ59o161bJ0btatevX5/v+W+++Ua+vzZs2KA9fPiwtmPHjtrKlStrU1NTc49p166d1tfXVxseHq79559/tNWqVdP26NEj9/nExEStu7u7tlevXtpjx45ply9frrWxsdHOnDkz95i9e/fK996kSZPke/HTTz/VWlhYaI8ePVpCr0Tp17ZtW+38+fPla3jo0CFt+/bttRUrVtQmJycX+rOoJD8XTRkDEJUI8YFQUAASb2yVSqW9ceNG7r7p06drHR0dtenp6fLxhx9+qK1bt26+7+vWrZv8oMkREBCgHT58eO7j7OxsrZeXl3bixInycUJCgvygXr16de4xJ0+elP+YhIWFFfNva1qe9tpT8Xo4AGk0Gq2Hh4d28uTJufvE33crKysZYgTxD6T4vv379+ce88cff2jNzMy0V69elY9//fVXrYuLS+77Thg9erS2Zs2auY+7du2q7dChQ756AgMDtUOGDNHTb2v44uLi5Gu/e/fuQn8WldTnoqnjLTBSVFhYmGxGd3d3z93Xtm1buQDg8ePHc48RTfp5iWPEfiEjIwNRUVH5jhHruYnHOceI5zMzM/MdI5rxK1asmHsM6a4wrz3p14ULF3Djxo1810CshSRud+RcA/GnuO3l7++fe4w4XlyriIiI3GOee+45WFpa5nufids3d+/eLdR7kR6VmJgo/yxTpkyhP4tK6nPR1DEAkaLEB3feN7mQ81g896RjxIdBamoq4uPjkZ2dXeAxec8hPtgf7oeU9xjSXWFee9KvnNf5aX//RT+SvMzNzeU/yk97n+X9GY87hte6YBqNBu+99x6aNWuGevXqFfqzqKQ+F00dAxDpbMyYMbIj5pO2mJgYpcskIlKU6Oh87NgxrFixQulSqADmBe0kepKRI0ciJCTkicdUqVKlUOfy8PB4ZFRCzmgI8VzOnw+PkBCPxWgWMeJFrVbLraBj8p5DNAknJCTk+z+vvMeQ7lxdXZ/62pN+5bzO4jUXo8ByiMcNGzbMPSYuLi7f94kRRWJk2NPeZ3l/xuOO4bV+1FtvvYXff/9djuCrUKFC7v7CfBaV1OeiqWMLEOmsXLly8p71k7a8/QieJDg4GEePHs334bx9+3b5Jq5Tp07uMTt27Mj3feIYsV8QP8vPzy/fMaLpWTzOOUY8b2Fhke8Y0bdBDDXNOYZ0V5jXnvSrcuXK8h+0vNdA3AYRfXtyroH4U/yDK/qE5Ni5c6e8VqKvUM4x4h9r0T8l7/usZs2acHFxKdR7kR5MSSDCz/r16+VrLK5PXoX5LCqpz0WTp3QvbDJuly5dksM4x48fr7W3t5dfiy0pKSnfcM82bdrIIaNiCGe5cuUKHO45atQoOVpi2rRpBQ73FKNeFixYIEe8DB48WA73zDuKQgw9FcNRd+7cKYeeBgcHy42eTWFee3o24v2S894RH9tiagnxtXh/5QyDF6/5xo0btUeOHNF26tSpwGHwjRo10kZERGj//fdfbfXq1fMNgxejk8Qw+D59+sgh3OK6ivfdw8Pgzc3Ntd999518L44bN47D4B8ybNgwOeJ1165d2uvXr+duKSkphf4sKsnPRVPGAER61a9fP/mB/fD2999/5x5z8eJF7UsvvSTnHBFzXYwcOVKbmZmZ7zzi+IYNG8o5LapUqSKH1T9MzIMhPlTEMWL4p5jvJC/xj8Gbb74ph/qKD45XX31VfjDRs3vaa0/PRvz9L+h9JN5fOUPhP/vsMxlgxD94L774ovbUqVP5znH79m0ZeMT/iIjh1P3798/9H5EcYg6h5s2by3OUL19eBquHrVq1SlujRg15rcUw7M2bN+v5tzcsBV0nseX9zCrMZ1FJfS6aMjPxH6VboYiIiIhKEvsAERERkclhACIiIiKTwwBEREREJocBiIiIiEwOAxARERGZHAYgIiIiMjkMQERERGRyGICIiIjI5DAAERGVoOeffx5mZmZyO3ToUIHHXLx4MfeYnAVNiah4MQAR0TMLCQlB586dH9m/a9cu+Y+4WIizuBT2nDnHiU2lUsHJyQmNGjXChx9+iOvXr+v8cytVqoQpU6agOISGhsoa6tWrly/w5AQib29v+fzIkSOL5ecR0aMYgIjIqImVtq9du4b9+/dj9OjR+Ouvv2TwEKttK8XW1lau4G5ubl7g82q1Wj5vb29f4rURmQoGICIqUf/++y9atGgBGxsb2dLxzjvv4P79+7nPL168GP7+/nBwcJAhoGfPnoiLi8ttKXnhhRfk1y4uLrLVRLQ+PYmbm5s8T40aNdC9e3fs3bsX5cqVw7Bhw/LdlnrvvffyfZ9o0co5t3j+0qVLeP/993NblUTNjo6OWLNmTb7v27BhA+zs7JCUlFQMrxYR6QsDEBGVmHPnzqFdu3bo0qULjhw5gpUrV8pA9NZbb+Uek5mZiS+++AKHDx+WYUKEnpwgIgLT2rVrc1t2xG2in376SacaRPAaOnSoDEI5wepp1q1bhwoVKmDChAnyZ4pNhBwRqObPn5/vWPH49ddflwGOiEqvgttfiYh09Pvvvz9yyyY7Ozvf44kTJ6JXr165rS3Vq1fH1KlT0bJlS0yfPh3W1tYYMGBA7vFVqlSRzzdp0gTJycny/GXKlMlt2XF2di5SrbVq1ZJ/inAlzvM04meK21I5rVI5Bg0ahKZNm8pA5OnpKQPVli1b5G02Iird2AJERMVC3JoSnXjzbnPmzMl3jGjVWbBggQwyOVvbtm2h0Whw4cIFeUxUVBReeeUVVKxYUQYOEY6E2NjYYqtVq9XKP8WtrGcREBCAunXrYuHChfLxkiVL4OPjg+eee65Y6iQi/WELEBEVC3FLqFq1avn2XblyJd9j0YozZMgQ2e/nYSLwiH41IhCJbenSpbKvjgg+4nFGRkax1Xry5MnckV2CGCWWE4ry3oorDNEKNG3aNIwZM0be/urfv/8zBysi0j8GICIqMY0bN8aJEyceCUo5xMis27dv45tvvpH9fYQDBw7kO8bS0rLA22uFlZqailmzZslWGhGwBPFn3qHx4tzHjh3L7XCd83ML+pm9e/eWQ+vFrTrxu/Xr169IdRFRyeItMCIqMWIY+r59+2SnZ3GL7MyZM9i4cWNuJ2jRCiSCxs8//4zz589j06ZNskN0XuIWk2hhEX2Obt26JVuVnkT0y7lx44b8WStWrECzZs0QHx8v+xzl+N///ofNmzfLLSYmRo4Qe3ieIdFatGfPHly9elV+fw4xGu21117DqFGj0KZNG9lZmohKPwYgIioxDRo0wO7du3H69Gk5FF5MTDh27Fh4eXnltsSIPkKrV69GnTp1ZEvQd999l+8c5cuXx/jx4+UtJ3d393wjyApSs2ZNeX4/Pz95vlatWsnWHXH+HKLjtWi56du3r+xzJDpf5239EcQIMNFpumrVqrktRzkGDhwob9Hl7cCtC9EHSnjcvEBEVPzMtA/f+CYiIp2IuYvEHEFiwsWcW3SPI+YUEstb5J1VOjw8HMHBwbJFy9XVNXf/559/LqcCeNySGURUdGwBIiIqopSUFDm3kWhZEp27nxZ+cvz6669yBJzo83T27FlMnjwZvr6+ueFHdPwWz3/99dd6/g2ITBdbgIiIiki00Hz11VeyQ7Xoy1SYpStEHyLREVu4c+dObovQjBkz5C1CISsrS95uE6ysrHI7hBNR8WEAIiIiIpPDW2BERERkchiAiIiIyOQwABEREZHJYQAiIiIik8MARERERCaHAYiIiIhMDgMQERERmRwGICIiIoKp+T8LU4x9x8Sa2QAAAABJRU5ErkJggg==" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", + "\n", + "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", + "\n", + "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", + "\n" ] - }, - "metadata": { - "filenames": { - "image/png": "C:\\Users\\dkgun\\src\\dangunter\\examples\\idaes_examples\\notebooks\\_build\\jupyter_execute\\docs\\tut\\core\\flash_unit_doc_35_51.png" - } - }, - "output_type": "display_data" - } - ], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", - "Q = []\n", - "V = []\n", - "\n", - "for duty in np.linspace(-17000, 25000, 50):\n", - " # fix the heat duty\n", - " m.fs.flash.heat_duty.fix(duty)\n", - "\n", - " # append the value of the duty to the Q list\n", - " Q.append(duty)\n", - "\n", - " # print the current simulation\n", - " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", - "\n", - " # solve the model\n", - " status = solver.solve(m)\n", - "\n", - " # append the value for vapor fraction if the solve was successful\n", - " if solve_successful(status):\n", - " V.append(value(m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]))\n", - " print(\"... solve successful.\")\n", - " else:\n", - " V.append(0.0)\n", - " print(\"... solve failed.\")\n", - "\n", - "plt.figure(\"Purity\")\n", - "plt.plot(Q, V)\n", - "plt.grid()\n", - "plt.xlabel(\"Heat Duty [J]\")\n", - "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", - "\n", - "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", - "\n", - "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: \n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 137\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 72\n", - "\n", - "Total number of variables............................: 42\n", - " variables with only lower bounds: 3\n", - " variables with lower and upper bounds: 10\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 42\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", - " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", - " 3 0.0000000e+00 6.95e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 3\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 8.9144743362344083e-11 6.9545421865768731e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 8.9144743362344083e-11 6.9545421865768731e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 4\n", - "Number of objective gradient evaluations = 4\n", - "Number of equality constraint evaluations = 4\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 4\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 3\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n", - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.flash Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 5083.6 : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol mole / second 1.0000 0.54833 0.45167 \n", - " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", - " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", - " temperature kelvin 368.00 369.07 369.07 \n", - " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", - "====================================================================================\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", + "m.fs.flash.heat_duty.fix(0)\n", + "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "\n", + "# Unfix the heat_duty variable\n", + "m.fs.flash.heat_duty.unfix()\n", + "\n", + "# Todo: Add a new constraint (benzene mole fraction to 0.6)\n", + "m.benz_purity_con = Constraint(\n", + " expr=m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"] == 0.6\n", + ")\n", + "\n", + "# solve the problem\n", + "status = solver.solve(m, tee=True)\n", + "\n", + "# Check stream condition\n", + "m.fs.flash.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" } - ], - "source": [ - "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", - "m.fs.flash.heat_duty.fix(0)\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", - "\n", - "# Unfix the heat_duty variable\n", - "m.fs.flash.heat_duty.unfix()\n", - "\n", - "# Todo: Add a new constraint (benzene mole fraction to 0.6)\n", - "m.benz_purity_con = Constraint(\n", - " expr=m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"] == 0.6\n", - ")\n", - "\n", - "# solve the problem\n", - "status = solver.solve(m, tee=True)\n", - "\n", - "# Check stream condition\n", - "m.fs.flash.report()" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 3 -} + "nbformat": 4, + "nbformat_minor": 3 +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 19e3b691..7c93163d 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,27 +141,29 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -144,34 +174,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -186,7 +226,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -195,40 +235,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", + "\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -236,24 +419,32 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -262,22 +453,26 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -314,7 +509,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -322,24 +527,40 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -348,51 +569,79 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -400,25 +649,29 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -438,10 +691,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -451,34 +707,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -490,22 +801,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -513,14 +837,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -533,22 +855,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -556,7 +878,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -564,11 +886,17 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -577,28 +905,36 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -606,14 +942,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -629,7 +967,106 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 } ], "metadata": { @@ -654,4 +1091,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 6b4b3752..0e823872 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,36 +527,52 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -359,7 +609,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -367,30 +627,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -402,11 +668,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -415,79 +695,147 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -495,42 +843,120 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -550,10 +976,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -563,34 +992,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -602,22 +1086,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -625,14 +1122,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -645,22 +1140,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -668,7 +1163,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -676,18 +1171,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -700,7 +1198,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -731,11 +1229,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -744,27 +1475,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -797,18 +1528,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -816,14 +1776,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -839,17 +1801,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -868,7 +1931,102 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 } ], "metadata": { @@ -893,4 +2051,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 562af431..62609b47 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,50 +110,64 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Use the pprint method on the model, i.e. m.pprint(), to see what is currently contained in the model.\n", - "
" - ] + ], + "outputs": [], + "execution_count": 3 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -145,34 +178,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -187,7 +230,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -196,105 +239,249 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, - "metadata": {}, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", "outputs": [], - "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" - ] + "execution_count": 9 }, { + "metadata": {}, "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", "\n", "
\n", "Inline Exercise:\n", - "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, "cell_type": "code", - "execution_count": 10, + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { "metadata": { - "tags": [ - "solution" - ] + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "" + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "## 4 Set Operating Conditions\n", "\n", - "# Todo: Call the python help on the degrees_of_freedom function\n", - "help(degrees_of_freedom)" + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "
\n", - "Inline Exercise:\n", - "Now print the degrees of freedom for your model. The result should be 7.\n", - "
" + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, + "tags": [ + "solution" + ] + }, "cell_type": "code", - "execution_count": 12, + "source": [ + "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Todo: Call the python help on the degrees_of_freedom function\n", + "help(degrees_of_freedom)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 + }, + { "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "code", - "execution_count": 13, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.334804Z", + "start_time": "2025-06-06T16:45:50.327991Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 7" - ] + ], + "outputs": [], + "execution_count": 19 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -331,22 +518,20 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Write the code below to specify the inlet conditions and unit specifications described above\n", - "
" + "\n" ] }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -358,124 +543,242 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" - ] + ], + "outputs": [], + "execution_count": 21 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "
\n", - "Inline Exercise:\n", - "Check the degrees of freedom again to ensure that the system is now square. You should see that the degrees of freedom is now 0.\n", - "
" + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "code", - "execution_count": 18, "metadata": { "tags": [ "testing" ] }, + "cell_type": "code", "outputs": [], + "execution_count": 24, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", - "
\n", - "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", - "
" + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" ] }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", - "
\n", - "Inline Exercise:\n", - "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", - "
" + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" ] }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "code", - "execution_count": 23, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.975773Z", + "start_time": "2025-06-06T17:04:32.972754Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ - "# Check for optimal solution\n", + "# Check for an optimal solution\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert status.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 38 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -495,10 +798,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -508,38 +814,95 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "code", - "execution_count": 26, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:39.229802Z", + "start_time": "2025-06-06T17:04:39.132903Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check optimal solution values\n", "import pytest\n", @@ -563,13 +926,15 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(368, abs=1e-3)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 41 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -581,38 +946,38 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", - "
" + "\n" ] }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -625,7 +990,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -656,27 +1021,248 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Repeat the exercise above, but create a figure showing the heat duty vs. the mole fraction of Benzene in the vapor outlet. Remove any unnecessary printing to create cleaner results.\n", - "
" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -709,33 +1295,250 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", - "
\n" + "\n" ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -754,17 +1557,110 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check for solver status\n", "assert status.solver.termination_condition == TerminationCondition.optimal\n", @@ -789,7 +1685,9 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(369.07, abs=1e-2)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": null } ], "metadata": { @@ -814,4 +1712,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 6b4b3752..0e823872 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,36 +527,52 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -359,7 +609,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -367,30 +627,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -402,11 +668,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -415,79 +695,147 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -495,42 +843,120 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -550,10 +976,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -563,34 +992,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -602,22 +1086,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -625,14 +1122,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -645,22 +1140,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -668,7 +1163,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -676,18 +1171,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -700,7 +1198,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -731,11 +1229,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -744,27 +1475,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -797,18 +1528,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -816,14 +1776,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -839,17 +1801,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -868,7 +1931,102 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 } ], "metadata": { @@ -893,4 +2051,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index a7645f92..2fca2a80 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,7 +25,9 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "markdown", @@ -32,20 +36,34 @@ "\n", "# HDA Flowsheet Simulation and Optimization\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", "## Learning outcomes\n", "\n", "\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", + "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", - " - Adding additional constraints \n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "\n", "## Problem Statement\n", @@ -81,7 +99,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Importing required pyomo and idaes components\n", + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", "\n", "\n", "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", @@ -100,9 +119,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, "source": [ "from pyomo.environ import (\n", " Constraint,\n", @@ -115,44 +137,60 @@ " value,\n", ")\n", "from pyomo.network import Arc, SequentialDecomposition" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", "- Mixer\n", "- Heater\n", "- StoichiometricReactor\n", "- **Flash**\n", "- Separator (splitter) \n", - "- PressureChanger" + "- PressureChanger\n", + "- Product" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, "source": [ "from idaes.core import FlowsheetBlock" - ] + ], + "outputs": [], + "execution_count": 3 }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", ")" - ] + ], + "outputs": [], + "execution_count": 4 }, { "cell_type": "markdown", @@ -166,30 +204,38 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } }, - "outputs": [], "source": [ "# Todo: import flash model from idaes.models.unit_models" - ] + ], + "outputs": [], + "execution_count": 5 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } }, - "outputs": [], "source": [ "# Todo: import flash model from idaes.models.unit_models\n", "from idaes.models.unit_models import Flash" - ] + ], + "outputs": [], + "execution_count": 6 }, { "cell_type": "markdown", @@ -200,24 +246,31 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, "source": [ "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", "from idaes.core.solvers import get_solver\n", "from idaes.core.util.exceptions import InitializationError" - ] + ], + "outputs": [], + "execution_count": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Importing required thermo and reaction package\n", + "### 1.2 Importing required thermo and reaction package\n", "\n", "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", "\n", @@ -233,32 +286,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, "source": [ "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] + ], + "outputs": [], + "execution_count": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Constructing the Flowsheet\n", + "## 2 Constructing the Flowsheet\n", "\n", "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 9 }, { "cell_type": "markdown", @@ -269,34 +332,48 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, "source": [ "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", " property_package=m.fs.thermo_params\n", ")" - ] + ], + "outputs": [], + "execution_count": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Adding Unit Models\n", + "### 2.1 Adding Unit Models\n", "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", + " num_inlets=3,\n", ")\n", "\n", "m.fs.H101 = Heater(\n", @@ -304,11 +381,17 @@ " has_pressure_change=False,\n", " has_phase_equilibrium=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 11 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
\n", "Inline Exercise:\n", @@ -325,26 +408,32 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } }, - "outputs": [], "source": [ "# Todo: Add reactor with the specifications above" - ] + ], + "outputs": [], + "execution_count": 12 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } }, - "outputs": [], "source": [ "# Todo: Add reactor with the specifications above\n", "m.fs.R101 = StoichiometricReactor(\n", @@ -354,7 +443,9 @@ " has_heat_transfer=True,\n", " has_pressure_change=False,\n", ")" - ] + ], + "outputs": [], + "execution_count": 13 }, { "cell_type": "markdown", @@ -370,29 +461,35 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", " has_heat_transfer=True,\n", " has_pressure_change=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 14 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -412,25 +509,60 @@ " has_heat_transfer=True,\n", " has_pressure_change=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Connecting Unit Models using Arcs\n", + "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] + ], + "outputs": [], + "execution_count": 17 }, { "cell_type": "markdown", @@ -439,39 +571,57 @@ "\n", "![](HDA_flowsheet.png) \n", "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" ] }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } }, - "outputs": [], "source": [ "# Todo: Connect the H101 outlet to R101 inlet" - ] + ], + "outputs": [], + "execution_count": 18 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } }, - "outputs": [], "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] + ], + "outputs": [], + "execution_count": 19 }, { "cell_type": "markdown", @@ -482,16 +632,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 }, { "cell_type": "markdown", @@ -502,18 +678,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] + ], + "outputs": [], + "execution_count": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Adding expressions to compute purity and operating costs\n", + "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", "\n", @@ -529,9 +710,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, "source": [ "m.fs.purity = Expression(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -540,7 +724,9 @@ " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", " )\n", ")" - ] + ], + "outputs": [], + "execution_count": 23 }, { "cell_type": "markdown", @@ -551,14 +737,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" - ] + ], + "outputs": [], + "execution_count": 24 }, { "cell_type": "markdown", @@ -575,14 +766,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" - ] + ], + "outputs": [], + "execution_count": 25 }, { "cell_type": "markdown", @@ -593,78 +789,143 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." ] }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Fixing feed conditions\n", + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", "\n", "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, "source": [ "print(degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.996567Z", + "start_time": "2025-06-11T22:13:28.973555Z" + } }, - "outputs": [], "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" - ] + ], + "outputs": [], + "execution_count": 29 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", "
    \n", "
  • FH2 = 0.30 mol/s
  • \n", "
  • FCH4 = 0.02 mol/s
  • \n", @@ -677,39 +938,49 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Fixing unit model specifications\n", + "### 4.2 Fixing unit model specifications\n", "\n", "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.fix(600)" - ] + ], + "outputs": [], + "execution_count": 32 }, { "cell_type": "markdown", @@ -720,9 +991,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", @@ -736,7 +1010,9 @@ "\n", "m.fs.R101.conversion.fix(0.75)\n", "m.fs.R101.heat_duty.fix(0)" - ] + ], + "outputs": [], + "execution_count": 33 }, { "cell_type": "markdown", @@ -747,17 +1023,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" - ] + ], + "outputs": [], + "execution_count": 34 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -773,30 +1058,38 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } }, - "outputs": [], "source": [ "# Todo: Set conditions for Flash F102" - ] + ], + "outputs": [], + "execution_count": 35 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } }, - "outputs": [], "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" - ] + ], + "outputs": [], + "execution_count": 36 }, { "cell_type": "markdown", @@ -807,17 +1100,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" - ] + ], + "outputs": [], + "execution_count": 37 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -829,68 +1131,114 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } }, - "outputs": [], "source": [ "# Todo: print the degrees of freedom" - ] + ], + "outputs": [], + "execution_count": 38 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } }, - "outputs": [], "source": [ "print(degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.304978Z", + "start_time": "2025-06-11T22:13:29.282394Z" + } }, - "outputs": [], "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" - ] + ], + "outputs": [], + "execution_count": 40 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Initialization\n", + "## 5 Initializing the Model\n", + "\n", "\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", "\n", - "![](HDA_flowsheet.png) \n" + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -901,7 +1249,9 @@ "G = seq.create_graph(m)\n", "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", "order = seq.calculation_order(G)" - ] + ], + "outputs": [], + "execution_count": 41 }, { "cell_type": "markdown", @@ -912,13 +1262,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 }, { "cell_type": "markdown", @@ -929,15 +1292,32 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { - "scrolled": true + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } }, - "outputs": [], "source": [ "for o in order:\n", " print(o[0].name)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 }, { "cell_type": "markdown", @@ -948,25 +1328,28 @@ "![](HDA_tear_stream.png) \n", "\n", "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Liq\", \"benzene\"): 1e-5,\n", " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -974,7 +1357,9 @@ "\n", "# Pass the tear_guess to the SD tool\n", "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] + ], + "outputs": [], + "execution_count": 44 }, { "cell_type": "markdown", @@ -985,9 +1370,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, "source": [ "def function(unit):\n", " try:\n", @@ -996,7 +1384,9 @@ " except InitializationError:\n", " solver = get_solver()\n", " solver.solve(unit)" - ] + ], + "outputs": [], + "execution_count": 45 }, { "cell_type": "markdown", @@ -1007,165 +1397,1060 @@ }, { "cell_type": "code", - "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "seq.run(m, function)" + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", "source": [ "
    \n", "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
    \n", "results = solver.solve(m, tee=True)\n", "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
    \n" ] }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } }, - "outputs": [], "source": [ "# Create the solver object\n", "\n", - "\n", "# Solve the model" - ] + ], + "outputs": [], + "execution_count": 55 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } }, - "outputs": [], "source": [ "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", + "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.344624Z", + "start_time": "2025-06-11T22:13:32.341522Z" + } }, - "outputs": [], "source": [ "# Check solver solve status\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert results.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 57 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Analyze the results of the square problem\n", - "\n", + "## 7 Analyze the results\n", "\n", - "What is the total operating cost? " + "\n" ] }, { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, "cell_type": "code", - "execution_count": null, + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.166006Z", + "start_time": "2025-06-11T22:13:34.094011Z" + } }, - "outputs": [], "source": [ "import pytest\n", "\n", "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 61 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.213201Z", + "start_time": "2025-06-11T22:13:34.210228Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "\n", "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 63 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -1174,25 +2459,33 @@ "\n", "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", + "## 8 Optimization\n", "\n", "\n", "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", @@ -1219,12 +2512,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] + ], + "outputs": [], + "execution_count": 65 }, { "cell_type": "markdown", @@ -1235,19 +2533,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", "m.fs.F101.vap_outlet.temperature.unfix()\n", "m.fs.F102.vap_outlet.temperature.unfix()" - ] + ], + "outputs": [], + "execution_count": 66 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1260,43 +2567,55 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } }, - "outputs": [], "source": [ "# Todo: Unfix deltaP for F102" - ] + ], + "outputs": [], + "execution_count": 67 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } }, - "outputs": [], "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" - ] + ], + "outputs": [], + "execution_count": 68 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.535666Z", + "start_time": "2025-06-11T22:13:34.502099Z" + } }, - "outputs": [], "source": [ "assert degrees_of_freedom(m) == 5" - ] + ], + "outputs": [], + "execution_count": 69 }, { "cell_type": "markdown", @@ -1315,17 +2634,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" - ] + ], + "outputs": [], + "execution_count": 70 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1337,31 +2665,39 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } }, - "outputs": [], "source": [ "# Todo: Set the bounds for reactor outlet temperature" - ] + ], + "outputs": [], + "execution_count": 71 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } }, - "outputs": [], "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", "m.fs.R101.outlet.temperature[0].setlb(600)\n", "m.fs.R101.outlet.temperature[0].setub(800)" - ] + ], + "outputs": [], + "execution_count": 72 }, { "cell_type": "markdown", @@ -1372,9 +2708,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -1382,7 +2721,9 @@ "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] + ], + "outputs": [], + "execution_count": 73 }, { "cell_type": "markdown", @@ -1393,19 +2734,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, "source": [ "m.fs.overhead_loss = Constraint(\n", " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", ")" - ] + ], + "outputs": [], + "execution_count": 74 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1417,32 +2767,40 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } }, - "outputs": [], "source": [ "# Todo: Add minimum product flow constraint" - ] + ], + "outputs": [], + "execution_count": 75 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } }, - "outputs": [], "source": [ "# Todo: Add minimum product flow constraint\n", "m.fs.product_flow = Constraint(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", ")" - ] + ], + "outputs": [], + "execution_count": 76 }, { "cell_type": "markdown", @@ -1453,12 +2811,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] + ], + "outputs": [], + "execution_count": 77 }, { "cell_type": "markdown", @@ -1472,43 +2835,186 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, "source": [ "results = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.223076Z", + "start_time": "2025-06-11T22:13:35.219792Z" + } }, - "outputs": [], "source": [ "# Check for solver solve status\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert results.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 79 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Optimization Results\n", + "### 8.1 Optimization Results\n", "\n", "Display the results and product specifications" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -1523,21 +3029,93 @@ "print()\n", "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.348144Z", + "start_time": "2025-06-11T22:13:35.343061Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 81 }, { "cell_type": "markdown", @@ -1548,49 +3126,66 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.448075Z", + "start_time": "2025-06-11T22:13:35.443091Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, + ], "outputs": [], - "source": [] + "execution_count": 83 } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 2d862e0d..329c0c99 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1,1363 +1,2698 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"reaction_package\": m.fs.reaction_params
    • \n", - "
    • \"has_heat_of_reaction\": True
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
    \n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
      \n", - "
    • 2.2E-4 dollars/kW for H101
    • \n", - "
    • 1.9E-4 dollars/kW for F102
    • \n", - "
    \n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
      \n", - "
    • FH2 = 0.30 mol/s
    • \n", - "
    • FCH4 = 0.02 mol/s
    • \n", - "
    • Remaining components = 1e-5 mol/s
    • \n", - "
    • T = 303.2 K
    • \n", - "
    • P = 350000 Pa
    • \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
      \n", - "
    • T = 375 K
    • \n", - "
    • deltaP = -200000
    • \n", - "
    \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
    \n", + "Maintainer: Tanner Polley
    \n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
      \n", + "
    • hda_ideal_VLE as thermo_props
    • \n", + "
    • hda_reaction as reaction_props
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
      \n", + "
    • 2.2E-4 dollars/kW for H101
    • \n", + "
    • 1.9E-4 dollars/kW for F102
    • \n", + "
    \n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
      \n", + "
    • FH2 = 0.30 mol/s
    • \n", + "
    • FCH4 = 0.02 mol/s
    • \n", + "
    • Remaining components = 1e-5 mol/s
    • \n", + "
    • T = 303.2 K
    • \n", + "
    • P = 350000 Pa
    • \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index bcdc90bb..91c14462 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1,1344 +1,2698 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"reaction_package\": m.fs.reaction_params
    • \n", - "
    • \"has_heat_of_reaction\": True
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
    \n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
      \n", - "
    • 2.2E-4 dollars/kW for H101
    • \n", - "
    • 1.9E-4 dollars/kW for F102
    • \n", - "
    \n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
      \n", - "
    • FH2 = 0.30 mol/s
    • \n", - "
    • FCH4 = 0.02 mol/s
    • \n", - "
    • Remaining components = 1e-5 mol/s
    • \n", - "
    • T = 303.2 K
    • \n", - "
    • P = 350000 Pa
    • \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
      \n", - "
    • T = 375 K
    • \n", - "
    • deltaP = -200000
    • \n", - "
    \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
    \n", + "Maintainer: Tanner Polley
    \n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
      \n", + "
    • hda_ideal_VLE as thermo_props
    • \n", + "
    • hda_reaction as reaction_props
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"reaction_package\": m.fs.reaction_params
    • \n", + "
    • \"has_heat_of_reaction\": True
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
      \n", + "
    • 2.2E-4 dollars/kW for H101
    • \n", + "
    • 1.9E-4 dollars/kW for F102
    • \n", + "
    \n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
      \n", + "
    • FH2 = 0.30 mol/s
    • \n", + "
    • FCH4 = 0.02 mol/s
    • \n", + "
    • Remaining components = 1e-5 mol/s
    • \n", + "
    • T = 303.2 K
    • \n", + "
    • P = 350000 Pa
    • \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
      \n", + "
    • T = 375 K
    • \n", + "
    • deltaP = -200000
    • \n", + "
    \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
    \n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 6f8b47f4..7e8b3ff6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1,1483 +1,3043 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 415cf48c..14dbf8bc 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1,1498 +1,2868 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 29" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "import pytest\n", - "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert degrees_of_freedom(m) == 5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check for solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", - "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.996567Z", + "start_time": "2025-06-11T22:13:28.973555Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 29" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.304978Z", + "start_time": "2025-06-11T22:13:29.282394Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 0" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.344624Z", + "start_time": "2025-06-11T22:13:32.341522Z" + } + }, + "source": [ + "# Check solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.166006Z", + "start_time": "2025-06-11T22:13:34.094011Z" + } + }, + "source": [ + "import pytest\n", + "\n", + "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" + ], + "outputs": [], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.213201Z", + "start_time": "2025-06-11T22:13:34.210228Z" + } + }, + "source": [ + "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" + ], + "outputs": [], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.535666Z", + "start_time": "2025-06-11T22:13:34.502099Z" + } + }, + "source": [ + "assert degrees_of_freedom(m) == 5" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.223076Z", + "start_time": "2025-06-11T22:13:35.219792Z" + } + }, + "source": [ + "# Check for solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.348144Z", + "start_time": "2025-06-11T22:13:35.343061Z" + } + }, + "source": [ + "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", + "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" + ], + "outputs": [], + "execution_count": 81 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.448075Z", + "start_time": "2025-06-11T22:13:35.443091Z" + } + }, + "source": [ + "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" + ], + "outputs": [], + "execution_count": 83 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 6f8b47f4..7e8b3ff6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1,1483 +1,3043 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file From 3604a411280ab0a915f8fa029d49383fa5782926 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 12 Jun 2025 18:37:53 -0600 Subject: [PATCH 02/36] Flash Unite and HDA Flowsheet Tutorial Revisions to reflect changes to initialization and scaling --- .../notebooks/docs/tut/core/flash_unit.ipynb | 1 + .../docs/tut/core/flash_unit_doc.ipynb | 1 + .../docs/tut/core/flash_unit_exercise.ipynb | 1 + .../docs/tut/core/flash_unit_solution.ipynb | 1 + .../docs/tut/core/flash_unit_test.ipynb | 1 + .../docs/tut/core/flash_unit_usr.ipynb | 1 + .../docs/tut/core/hda_flowsheet.ipynb | 107 ++++++++++-------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 103 +++++++++-------- .../tut/core/hda_flowsheet_exercise.ipynb | 105 +++++++++-------- .../tut/core/hda_flowsheet_solution.ipynb | 107 ++++++++++-------- .../docs/tut/core/hda_flowsheet_test.ipynb | 103 +++++++++-------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 107 ++++++++++-------- 12 files changed, 347 insertions(+), 291 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index 2fe01927..b01b3183 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 5f3b9777..27292328 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 7c93163d..8f3789d9 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 0e823872..0557e0df 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 62609b47..9bce54d7 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 0e823872..0557e0df 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 2fca2a80..af8206a3 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1411,9 +1409,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1433,7 +1431,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1511,7 +1509,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1549,27 +1546,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1938,7 +1941,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1973,10 +1978,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2036,7 +2041,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2250,7 +2255,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2278,7 +2285,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -3133,7 +3140,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -3143,7 +3151,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 329c0c99..be783094 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -348,11 +351,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -472,14 +473,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -557,7 +555,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1204,9 +1202,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1226,7 +1224,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1304,7 +1302,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1342,27 +1339,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1731,7 +1734,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1766,10 +1771,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1791,7 +1796,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -1977,7 +1982,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2639,7 +2644,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2649,7 +2655,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 91c14462..6a51e39c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -347,11 +350,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -485,14 +486,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -583,7 +581,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1272,9 +1270,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1294,7 +1292,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1372,7 +1370,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1410,27 +1407,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1799,7 +1802,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1834,10 +1839,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1906,7 +1911,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -1934,7 +1941,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2639,7 +2646,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2649,7 +2657,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 7e8b3ff6..0d19ffad 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1375,9 +1373,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1397,7 +1395,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1475,7 +1473,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1513,27 +1510,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1902,7 +1905,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1937,10 +1942,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2000,7 +2005,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2194,7 +2199,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2222,7 +2229,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2984,7 +2991,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2994,7 +3002,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 14dbf8bc..16908e20 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -348,11 +351,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -472,14 +473,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -557,7 +555,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1240,9 +1238,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1262,7 +1260,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1340,7 +1338,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1378,27 +1375,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1767,7 +1770,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1802,10 +1807,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1827,7 +1832,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2033,7 +2038,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2788,7 +2793,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2798,7 +2804,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 7e8b3ff6..0d19ffad 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1375,9 +1373,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1397,7 +1395,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1475,7 +1473,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1513,27 +1510,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1902,7 +1905,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1937,10 +1942,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2000,7 +2005,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2194,7 +2199,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2222,7 +2229,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2984,7 +2991,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2994,7 +3002,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { From 6359e8170e1892057574255a5f81b541bd09e5c4 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Fri, 13 Jun 2025 17:14:09 -0600 Subject: [PATCH 03/36] Updated version numbers for GitHub Actions to version 4 --- .github/workflows/core.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 0151406d..ec53a8f5 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -66,7 +66,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run Spell Checker uses: crate-ci/typos@master @@ -92,7 +92,7 @@ jobs: - os: win64 runner-image: windows-2022 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Conda environment uses: conda-incubator/setup-miniconda@v2.2.0 with: @@ -112,7 +112,7 @@ jobs: pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ - name: Upload pytest-xdist worker logs if: success() || failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pytest_worker_logs path: "tests_*.log" From f819b5e53c2b75c2d2544204c6a8835f8938e26a Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 16 Jun 2025 11:16:17 -0700 Subject: [PATCH 04/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index ec53a8f5..59bf436a 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -40,8 +40,7 @@ env: defaults: run: - # -l: login shell, needed when using Conda run: - shell: bash -l {0} + shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash -l {0}' }} jobs: @@ -78,19 +77,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: - - '3.9' - - '3.10' - - '3.11' - - '3.12' - os: - - linux - - win64 - include: - - os: linux - runner-image: ubuntu-20.04 - - os: win64 - runner-image: windows-2022 + python-version: [3.9, 3.10, 3.11, 3.12] + os: [ubuntu-20.04, windows-2022] steps: - uses: actions/checkout@v4 - name: Set up Conda environment @@ -111,8 +99,8 @@ jobs: ls idaes_examples pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ - name: Upload pytest-xdist worker logs - if: success() || failure() + if: always() uses: actions/upload-artifact@v4 with: - name: pytest_worker_logs - path: "tests_*.log" + name: pytest_worker_logs-${{ matrix.os }}-py${{ matrix.python-version }} + path: tests_*.log \ No newline at end of file From 66753458239048d1edd2a9bbdf71c10c48ed4932 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 16 Jun 2025 12:03:58 -0700 Subject: [PATCH 05/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 59bf436a..6d292414 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -40,7 +40,8 @@ env: defaults: run: - shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash -l {0}' }} + # -l: login shell, needed when using Conda run: + shell: bash -l {0} jobs: From 4e40e56469b7b5e36b2180ff664cf6e374a1d3e2 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 16 Jun 2025 13:14:50 -0700 Subject: [PATCH 06/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 6d292414..1375e99e 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -66,7 +66,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v4 + uses: actions/checkout@v3 - name: Run Spell Checker uses: crate-ci/typos@master @@ -78,10 +78,21 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.9, 3.10, 3.11, 3.12] - os: [ubuntu-20.04, windows-2022] + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + os: + - linux + - win64 + include: + - os: linux + runner-image: ubuntu-20.04 + - os: win64 + runner-image: windows-2022 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Set up Conda environment uses: conda-incubator/setup-miniconda@v2.2.0 with: @@ -98,10 +109,10 @@ jobs: run: | pwd ls idaes_examples - pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ + pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ - name: Upload pytest-xdist worker logs - if: always() - uses: actions/upload-artifact@v4 + if: success() || failure() + uses: actions/upload-artifact@v3 with: - name: pytest_worker_logs-${{ matrix.os }}-py${{ matrix.python-version }} - path: tests_*.log \ No newline at end of file + name: pytest_worker_logs + path: "tests_*.log" \ No newline at end of file From 0051c10ac1fd7bced472533afacb1c5438b67ab5 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 16 Jun 2025 13:18:44 -0700 Subject: [PATCH 07/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 1375e99e..70f5c84a 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -112,7 +112,7 @@ jobs: pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ - name: Upload pytest-xdist worker logs if: success() || failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pytest_worker_logs path: "tests_*.log" \ No newline at end of file From e352c2d03113c19537d04a4147eac9bc2c576c53 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Tue, 17 Jun 2025 10:25:11 -0700 Subject: [PATCH 08/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 70f5c84a..b0ec0cca 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -114,5 +114,5 @@ jobs: if: success() || failure() uses: actions/upload-artifact@v4 with: - name: pytest_worker_logs + name: pytest-xdist-logs-${{ matrix.python-version }}-${{ runner.os }} path: "tests_*.log" \ No newline at end of file From f8f3af4482f6b2f1d09cb47e148416106e52bff2 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Tue, 17 Jun 2025 17:33:50 -0700 Subject: [PATCH 09/36] Updated version numbers for GitHub Actions to version 4 and other issues that were causing a failed pytest --- .github/workflows/core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index b0ec0cca..42610e1f 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -88,7 +88,7 @@ jobs: - win64 include: - os: linux - runner-image: ubuntu-20.04 + runner-image: ubuntu-latest - os: win64 runner-image: windows-2022 steps: From b3f5eb1ad34be70010084b3a66b2d5ea2ad4a180 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Tue, 24 Jun 2025 13:55:11 -0700 Subject: [PATCH 10/36] Revised both Tutorials based on feedback and ensured they both work as intended --- .../notebooks/docs/tut/core/HDA_flowsheet.png | Bin 52808 -> 85876 bytes .../notebooks/docs/tut/core/flash_unit.ipynb | 28 +- .../docs/tut/core/flash_unit_doc.ipynb | 28 +- .../docs/tut/core/flash_unit_exercise.ipynb | 28 +- .../docs/tut/core/flash_unit_solution.ipynb | 28 +- .../docs/tut/core/flash_unit_test.ipynb | 28 +- .../docs/tut/core/flash_unit_usr.ipynb | 28 +- .../docs/tut/core/hda_flowsheet.ipynb | 1390 ++++++++--------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 1277 +++++++-------- .../tut/core/hda_flowsheet_exercise.ipynb | 946 +++++------ .../tut/core/hda_flowsheet_solution.ipynb | 1354 ++++++++-------- .../docs/tut/core/hda_flowsheet_test.ipynb | 1313 ++++++++-------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 1354 ++++++++-------- 13 files changed, 3831 insertions(+), 3971 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/HDA_flowsheet.png b/idaes_examples/notebooks/docs/tut/core/HDA_flowsheet.png index 837bafb5eb57c210d7a56baf5df40d5452f15b47..e3a20f5fd2543f20a770bc2b2322226e4ad2cb18 100644 GIT binary patch literal 85876 zcmce;2UJsO@HZS?*WMKsm7;(w(z|p!AWi8Isz4|qfK=(Y7S=)$5dsLTO0UvF6HrhP z2_P+ygd!p!gx)*v+)#G^^*!G?-}mLPZgP`*pEl3TZ+Uq%MDX>%|Y=pW(wc%S$SkP^he+Jxiv)!{=QN3VKc` z)bT^ee_Otuo0Nl#jLz3|oi*$+&TgiT7AO^KGe>(T_{6G)!C0GF_zsKSfv5UgYw9}d zswhjE+2i<3&Fybn@ZH5Zz}+a6wA@_>Q!}iEGwW>&OKUqB&e7sBPF8Dk8BQHh6#*58 zD;8GP3LcIY8Xl^eW*%5G33E<4*?qgE?@GcGa2C#{taov?c21IaWzNzcED7(C%lv0$ zr5(*NlImBlum1u*$(*%vc6N~D=XY~+<8u?{vv;)Q7nG2Y;1>|$7ZT!yU+_A)+c}%w z<+XESTYtb+3nw#2YX@g*dplO-fu^_ZU7Tgky0}=IOJYnhqPNY>MR{+V3Y+r^3Ywep znwkp>@|p_^n~RGIUJ$|v-afnDyt6gtpZ4vX)~5j`gdh2aUyx4#=`!+OQq9rY0(yZo zDJv*V|NcK*ljcV{@~@7`u3dq#!n@6xL8fVQb}j5+O5I@YctY`eP^jf$#jBSz?-~s) z`)WqbM)xn5g|^Q$w$mQAmEZ<#{gzI=^Yo{-)x~|cu9W*#>8in17p?qMsLSg&%RTpE z;(D52RjPKk$tHY^;1?lV6ApgyIa4L|eBy1_g`|kKLhPSWBz2jr-~4ene8KNRcLb$W z8}6!or9}N&lqWJ6vap|d_u!B;OaHH_qR!F!c%_}9$2);~u=`*((Z1)<^HeLVx48D}?cKU#SbIg03C0#1^ ziCZl%OjB~LUxe`)+U(zwFmy5p9(AtY;lk}s1HSN-l$4*-9-=}a?+;8Q+L)VPHOkcC z3$O8bm7bn{^5jV&e+pjCI1Vjx@8ZS0ygX6?g`)ra)-6tL+man$ReKo`skYuYl-Y5) zhSz2+R;@w4>2I>{FO(OpzDe)$)>t(DrD(%SpHsZImuzfgR8+5Pah@$%XnJZ2f5nf> zECH6V>HA-Y%C9wcbfjygYDe@kwvfrmKYrZKv6XQA`Ii`uVjkAg)s^}Fy>yQBrMUc~ z(2bPTRN>l*2#G<$3g>wK6@W} zcV;VhJ{6Z5AsQi}PZ_SgyTTv0D9p9g z{_^F^lc!JTGFvLu^q={dnptXt3zG6#D#+_-Z58jfWGZ{OXZwA^-}R%j=$`V} z@F?27XHQFOt7QwU2~K&g*XHcw7IDvjfB=$(J#li|{Y!ZSf_^xgjje4i-(#~*HTK6v z<_9uP3&V!MKN=I4%v#~vXS~on;GFXIZN=%^M`-&rMY8JT>iQ=K=Ei#l2L>7@>*eIS zfBekyi5csJkv29p;g%K3!=D6*)ChRFzUdm(F*P;4!E{_HtzW3!JTu@T>)*!9gF2EP zQ%Td9_u1L%wARenu?t&jLn4A-m?BbwLJ{|m`}n**VfMDA>hqxgEJ&xOp&@SA-}nY6 zY0&uo{riL%_x&7mAusl8lT0qNAm?CIHAG!+()VD#p}ju6#EjZ@-wxic*8KM!H4M^h7PVl%Jq zVdqHB$WVm|#xN=(%HiVS+E1tQxf?*PJBr=Vi+wIzI(=8YsXo`PJ!A+G6&J7Rb*%1n zRN47OHAdPRCm*TD=(GH3EGya3;OtdT+_tS-Xtj4$R08Uvr7U?DPnI^1AS1z<`LI5q zYe8bDi9pgtR+IDzc14)U`~bzHiA~ntD-8_|uT`SN6vO4%cCBX5JZFkS z{=NbRLM^WwQ<`yhb3;!L4i4@z{whC#sHxy>P2N3XD}7ey^9RN}N*pho{#sL`;pCL# zEP)cXyiq#a=}A~t0AX?+X}3=Gp6m7}xyHTYH<)YFlo+|8JVUwL{qT6&usn-*b0j%3 zCMLt)XEI8gpLEKexbHzQGL3!_0zT=V$I#cWKYH@yiER(TuEU0^7RniO_jdVLqmZdo zg4T9Kv%01C7HdKkJ>wv$96x zMnQMZiHM0&N_i7%Xk-5Mdqd+$B<*NvclFxZS{rNY2ASD*vl7L<+qM$K6T9ulZW{`l z7{m!aw@FYiJKLiCyz**F#1FCiP4F~ad@pW_@Mw5Y5VrG5ko#~5p{CCA5Fe3 zJZhUex!7|izA)|@Pj{EX9^c=NGkaY3^y-nro@YK@V_sHq*Z33|2mANq*NJoM1H@^oc%;2Cr{Eph>$rJ6plx30_G| zU$gi&DNH?l@3Xg$8^K z3=Der%$1a$f;zn}FJIe@|6Fj6t}skWcdsg26unYS%wrl@xqki4Dvrq~ZJw+gcM7u| zv6?x5%|H4h1}zPeYlFr1Iu@QSeZ0q5*4eAXTXDjpL@;Pi=EE{_@iYmYJ`DN->uE4| z2TMxJLR5pf$9!*ix?gM0_#a1iC%=Dh@bKZoLz%vQ5deW!bt!KZz&B{hB6tSV5C`rKxIexBr-ayneOTUa&G(OZoueVML}K6q*C z=~?4gE;xKxaCB2s3);PVclmYIdgGC zH%TceoU!ca(2%BuTkrY7mP}h7qg{_|4V}6xt$hN+?Dq4^ zAuRb;j`)QOR<#AE85tY0Eo#z?=H`h#um(DqVg4as<~s)N6MHRV*g7YR4fv?X3o0a{RnhhDV*zE*8ZTt!=H@27f8Wl-wu?Sb zkM4F|s6D5prA3I>W4j|64f_0D%MS^@#;APQ)>@jM_Ma^O?b{t_S_GO#^tOvj9((fZ z*O$6hX7XRg#K@irZWbA38E1Q-EWK{9nKGs(_ZY@x&3(Ur;QHQuGR#4|??mbkjn4Z& zdK4NRjSJ&Y^!D}!b(b^4)=_UBi*0FcwgOuMiu^Jt@(&`P7AvjAc5S~;DRi=I7QYSp zzg}+jJp#5;t32)}*L)-gGD#7$MXJRcZPQ^sjg8G?dAc>- zNkl~CSLVuKX6Vb846Vyx7fQw}Pk{k`4)-+;G%rlkrt>nrRX{@u`LjJHm^8yU}*GTawAxtsg zoK~PP$B#VI(${X1(T^A7vI1JwJ`0>4}izfkYYU|H1%Y%5r!aeZfm!Md+OG^W2%a5pZZmD$X_4XT}p+j+)v{i&$Q z<7+n?<-V)Ay3^g|+M>+5Cn7LQf5X~)ZBH@W5N=h*xh9;bK3V#kIO+0?<`1KE1nW0X zqXT%vXd$;x);XnB-3~K|Tf8`hF_~7#EU_AsLs6PhGn!~QRy98|-=D;xSi2y^t z0qpGb!0%mh$+Vw(IS=(%E$7cNERk=^l$b?3hVctgP1d$9^0W^_q!F41x%2I|kes#; zMjKiE!ee@j z4gc)fKbKJotbbP1MHOiZUVhuy@VQR^x88S;CXJe5oiVYlGX|2sd{ zDVf#nF*#Ca-36dOQn@M2MSL)?vi1i0poFVgPnRZryvN$vuUTiiOZt{?m)=nWmVv$a(QB$cV1X_OvtN_=pEmf0F3 z0HQ53GcXykn`YcRY1NbCYB5Qb2XsD~qc*g8FK|Ng*3 zb_Nz?dawm~JfMDZ1oK-w(-`d;LqU?$k>!l~3k;|cJMY=*|zh-Hf2rWK&`c%u%kTN6gL5lS)gC5>=xc z!+6m|G2}t)Di}{{z$$VdwJ`9!|^L=WdiBfRq?MTV2(Z0QV@xzRhjY|9x95oTb zmQ(Pqde{|P6UKY%eyQ=wM0gPZr|G$#AX<>`(pxQ-lP9wSgxyPwIvi_wZES2B;hwYw zmeo0VQBl!>I;qiTbK*m>%jDQ(aR2yArb31$@pj~w@CVu;swzJ+XnFDr>2_J zxY^h$Y}FjbzF$Hn&U0qyG0i?UwRfz$Vu4n+f<+H6%}*}Wxs|?^8h!6{`ND+=uprc~ zcMSy{BfEspRot()>hzv9Tn=BIFeXl<2^in6{vwC8;%B`p_RPTSqLz_SMp_zAY8ZG( zV0@F4lNDiVw3k2J`;A24^Nq?)Nx1>CN$}v|RDJc109Xb5`1IxS^2_eh%-B^R97u!& z_fqp++qRxRe?EjdOd1<|M~?aX-MgDUWyUHhDqo325h^l+4qCQdrG~KD+1^~Dkudb( zj$$404rh%|5%+{GCi`kh;po*~1e_w`|D@B5ae0kjjAX_;k4fY3a80>sm*Ji(>*rlGsC1874-xx@A6CI#`&mR=xw z2%in^DNbBOr0w!Y1%OvtdV0xh@`1`bf6K|qX#oIY7_;R>(3pLE20FivB#bR7DIs(^ z*M(bw_5z8}0MI&I`0Sjpum*TcK4rd*{U?!uWjul{h{zLYu&1=qFi??&9d^h@MpRjS z5{FXQuf?v_l?Q%fuxxAH1z%9o`B$)`qoZw!mCtN(7kMNRX8M5K(mUt*_j2>qYR)yh z`MTatkI6x@3kt}Esp(ALj+73s$=Zeb)pk;lyun2i>_1^&3k;W1SM_fv^o>d@2!Z=w+o;t z@l00Fl?A|3Ha+Nn24A)p7hO>u2S4~G2|T4LnPcG;FAHvA2Gd7nS}YH%GXzRZ6SIh<_SnV7ce?G5CM3z^S}a- zEVzW7=kzlBe|c?OV)ol;2;E z{QX^ieLDk2@Oc@U|J12dO)!*RAR+|>ObA<0Tq%WxdZ0K%uLt7O^-QZnIEp|A0ib&H z=#lN>>PXkJ6t(onT(MaD{A54erlqfMlPWjyg^jRGKHq6FF?G>qwd3@B;%@?(YsMHc z&3=l{_sY`Kn%FPSE7lkLlh5%;33FB@A zf^l#)Ve5y}qLPy5y~nbrqB3goPLm z4-M57zEw8&ng8psD>_`Xur~}nRe8$(>iaJ8`52RITYDQ{JC=D)=$_$l-q$Ut57G{= zjTf4BU>HycDY|Sqhh|3g-Fw8WQo?X@A#yn&)iobDObKc=_AM!$c$wK&sZurS zGb@!NV$sm~n}P50bP+A1_-tM2t6@S~@hug#cIzzFLKt@c~`Ug>bibgtc+6D8n(fQ5iz>0Hy++0!%{Ezi9A zFnZYLv1`c}xs~xCM2Sbcb#i64VhNUc_i~Qs=1)&5Rp5n=8(W5{?|zLq;lZp3|3p|^ zT*Q?q{Q2>3P#n#`?}95&NE~`}%1%H@th*m?JM^qzMsnbhr^{e77mj@S0v%K&FmP-C zsuk}FT^TBFEKfbPU3R)z!vol*+KFd^{1QK=Js5UBOrxH%fB%|lU)CX3IqXUcFI$RF z7enuRRq}VhOSvWhrl|o09;5j zz$rmT5x+YLL=Ze?@aq!EG1+MQk`@Xxn6PQ{2O$UtFrASwE|=W}_P_V%PyBEau)|aS za!aP=w0rbzS6holqod~4w)}YKIXkkeo`c?I)I2qIWr`EXSNZ4;%dcO)-1PQd)>=K> z-&Y$o{ppC>FJgr7!pdx!Js}a-l%N8v+Q)8tAG0!_zOvQX)lP!_!a{3V#ufkl17T>p ztQMqs>Wb}AHC8ggv*gA|_Ns02BRZ5;2p*G50V~kl)MQ5UKXvkCNKJ3{42#FFGiYDQ z@+%EMB#=EYymE3~q^Nxel+Z|2O$G#DZEcP5+?v^%3aZ9tb!GYFsZ+vqlOe!;TGCko zXe3gGVeuQI9fAhd*2!QiUk3AMsulP?@u&mq^@AAr#5P7{aZM@pTqcWF0 zJkeW&TYS!=m;Gtxp`oJWogWWyzJ$l(!8{N&=?$fOg(&u$^78(9hBt5i4bD83MIC%x zz-eFW>IgRAR0F$0T5;}hrQ%2g>M*FXcQe1;^J}-u&nt86y@B-`fjAD%XhwkzZqF_{AMPFM!qM47RCF@IEHEv%$~xXJ*ruw`%FTqcvr zK#sznKEXBu_b84XVX_Fz1NueI$q)ueTLyGVdw=a(tg%};5JxgH9hBGrAz|U(@w-34 z{@=W5Lf|}c;sm~tWf9qu!8|?2F$N_bE(XRiL?TfW1Zv60_j2jG$lZv>K|F-~nW)If zsdlG&#qcYiN4@%`B%S)6wPYqGy(6s7*sp5)uJrq608FeST)qW-5F(}E#_NkJA~+Tn z0dIdVZcRCSqGp--<0{QXV73v;KofTi zJ$t{sz5)QsqP^xU;u>8%o0p%jHXw8aSWtTS19lrh{W7#WZK3O5@w$q|x1Hp>G+ve7 z8M`_kOZDiR$OXg(^R@8fcv(_H!nsr*pfzZ6D^;sjrxu~3DS!ok|NVE;^6{fb+b}wV z6OOq^oB)?cHj&*PvPLq7Q~38vLMZw6)ZG(bi1k8lXL&)x|FC;><9H`wimRfDSl$;)DR2KKl-UACYN-sSuHt zwk2@3Wm`N&;Nil;LP4pY1lq9Rpp2$)gz$;7)#cIDl$5X9!iJ!QJr;-a5mlLbZ1lKi z*>t-7!077AXzhfSxbbg_YfgXlix$uqzyH~$#oTBXoKa+p)e@(dO9 ztJ*;9%0O(cP0M+zAnYTL{%AKK1x34M?aP*30XqzU#($1D6A?Kdz4o)Og-lsn(sZ*f z!!HPkzkn!2T-5y?2O{ZlOND~B@%7GJ-TZ(- zGfQS7LB5cNA)Z46@TsAw_*mj7B1VVpU=fgR4T1snoV5e24&Qs8=iw3Yzs-CmICqT+ z6R^(g@!GX%zY2t&mx7X3ri_p^s)lQ*M zkZ`n4^nc-s40f$(2jGyN7Q1EYkw!X-^DOI`K?W5B8&+a2+pq>N?L|U`>n}fcxNw>d z2G*_wn`{el{a3GZbRmw4*_Ctp-p{N5zT8IGCjpmF{Kqlo=q|IlB{fH2!vt&0dGuN9 zUwqyca_hq7*EhfLY{hp`s8lU&ZA=&-!W2;H(5nwx{RJhTc@#tFfpmjwOEEC2Kg+bt zs4&qpBOTZ(8fk7B#r=r=-ks$=T?If&3}|idBC17#{6jZ{u@u2rURs+3)mL1p3YS3ROAWI^HB0 z8gu;T?>75tNN*SKwv%gZtubpc%KV>5u%taCW`XzXI04jKKOMQBw3x$6CGK<_E7eX(w*{K%i^wkvfd)bB(91SvS2$ z>x~lE+u)I3Z&aOW4XEB;f9Ay$`fQ=pPj5V8c*nc=M`Vc6yJZqnsK0Sf z+1fqsb_wfU7w}!v{O=+jZ}fzp{utEljnV3?A&L*7>_TzM=nt_7eg;w4;YAmY?@tUA z6$-oS?FE$R*G=}XO>gkc@kgOll4Z?g#cgWV+E;e#Uuj|#7(MbYzjouE((l0lA8NIq zj`dMa2miGp|36Qj*(9O`s^a3~BVZT!rG7oM`{8BGp$|)>&d!YNY@wXA#zu9>?TD~I zhVVh!Em0#=&R)rlj(*X(N=8ii7>Qu6N-SMpnFdb(Q61JbInHuE6yf%oJL1eE-)^FKqn zg?dbvH+a)@r~XkC@$lccQ|^Y)-WU3E!gT=)YRCLnz0xl{X3R=xhX7ZdG|?Kk9>OjU zalnXcs7bV^XE7iKV)hLsr4|wi6Gq=1lbV0ezIyW2NW7-8*Kbg!ep&zd3sXYyo9p}r z&0iOdNMrIWQM`)kO&OUf6Q%r7$Rs?DSl8_MjPfOmTb7jph6|drBNx)Lp2p&NFrWY0ass6;i)hoT;`WXn&-IqI%yC zTJzMWXbdAv^P01Oj5mxhrtj{fo0j|gb2*Gh-)AEx$(eh4*LO2s@Vum@R%#Z;i}NIL zJ5{^T?>je9d=2h`7ptm7&GFB#xO52pNssE~jb@JIP$56+=gP-J(BEcT#SnsAa3(L! zP6U~zBkMsN)b}T_l({%>0`zj9@6;V)ge$&eCf|+wo78QHxp8MVX{~-?LfT?IyRnSy zSE(@pUky&XGuGdi-_f$v)D>w#ynV0Ji9&TO=TQo2JZ8YAw%i&DBSAFr!9yD|e)z0e z!)5nD@d%3=vwc<09wyB^X2&2VachLdInqLD`K|G-OCyI76m@V@R1ae+D7}=Gi>1&( zWa2G6i$z?=k3eLkFN=kV?pW%D0K0Ws7)jr6$JGgJNd*^Z8c@xs}qVc?cEj2W)9QSB;`H`kq$s^z} z^JmJSuPMxZvG{o>#h+U@7h1jlU5os@fJ!T_%Ngfo}TmER42{1 z$N3^)tsxVLD)ti(;^bGbG4-rmn=29`$~MZB^DNcM*E7FJ^?J<5$Q-Zdk**!qh|vDH z{>Pf}@r$#jmKa4mW#gZnC+F>1BnoBxd2zHbsdYgac7U{8dtC0rR)jBwFv+^{WVIFw zH%Lt2EVT*a4O;$%-(F`VP=mh&iDI|NF?{QS!OV|N2gybj+2qE?1`F1N4kyv~fMVmX zhf0pC-~ZC9-0P9nklA$q63ps(qH&501GW~x$%oL*_6A})Z^bc?2QYdeM}ILj#DpEe zFbaP+Y4wZrT|mQKUv+aY#;_biHkP0Dnu3RAYmDc8uZ{B*`vZ6BXVBXi8&5TmCJ60{ zc&(Ue$;>O|*t#!x(n4WU^dKn~ANFN*D}6UZOp2RmoX~Ng%MO;*EL`^G;*RK(#dD9z zmqS8_Wm39>WW^vsEu`4)RCb5)0FEQ)^iYS{x%jEs=B{ z`VHx-Ua5jg@d$mt=seg^NWv+&dJoXxCeYw;sSnf8Nr4)Lzngx0OPTI5j>|9|bpSKNxU9p&(WK%);B8^Z79MkZrqC5V{Ko($Rrlnh<09&E(>K4>-M(o}nS zjLo5khMe_-0DfwPGA_10{#9>H`4ihr@Vwu6%m|BU=EHw(3`^%4r5xKk-+eB}mJ9<) zEna=ES1GbLcJ)HvP*VcuNb{3ddy$P9EU>Y|3T$>yhFiOR)`zJ=0)6epJ{fe4sC=vC z#i-TX+b^vH?F3nLe4RA?#+#crrp#!jX_>C5!;O+MCz{Oyd~%*~SwYnEdjld^Uk$vX zBV!7hkSS!}1gsg7^#`85B(P4%Yt_mvr|)N4{J_JuKXJ!(t?8dq81j$gt~eq`D`K_$ z9z0!AJ+QVh@t5dYF>6CB`W$^8V7PRZu0#ejayS$b%_5d&XoqaHkj>f1xtuJl2EYqZ zffX#?NPN0h=yqFIXZpp_zd#YCe^J!|_)DMoxD6@(kcLdW1z+I%SHB<&Gig4tOtj{& zziFTJhH(<6@FeR!84cKgsF&+{F?ds1;Y9&Th9>&F&?88b9F$>DwL<03j0#RTX~!*)VvKm2`BY*L11S864P78Wi-Y|c!&#PqSfx_R z>g6B^^NZF@Qh?X<7?Q6dX2%aa&ZKKb7toCC=$~#bYYXr}i*T0nikeQQaLut&z6xF_2>?PnS3efl!v<#NZ;0i8xn%gJ3qRZ4cuu1?9E4V3%Xj%p5iT)K-g4mTWHC($yw z1?Bg1J%TS#1}sZzS{jijH8)oihr=NX6vQu13iJnVc_a#>S9JP4g7Fc>MUI@TA)c&L!D zf{#ynZ)D$mQ9T553?ccrHoI1{4q)k8P8Kp0_3|dEC%I>(I$#;LmatKpz`WO6?-)#Ts3nsWIATP}xJ?jSA z86gTsXBX3*7M6WdM_h{;_Fmr)5kOf0bZed!v>JRE)Dt%yK)`O-_e87y@y)Z2r(Ut5 zUrxK_MVUxVSYlcJ$dj;~^o$Gwp{Aw=xGM`t{3}SH1K~)qv-~sZ|tz$q<5MO;6{f>+lmQF7Taui(Uyo&V*1-{>s z5p~upQB{(v0ZIVbFY$E-2=bi>eNg|WEe;oOf&0!tV?2qcGB9v|PWsT0Eu@Spg+N@a z*7d4o-K#7@YdYGJ7LnK4X@s_y><5KL&o`tu#sy^+_r%il5X<$OC4W-N3R8}BqV(kL zOn}db#(&lObZTn$+#`1l2Id>unwo#Gv0Z`GRmdvJ3V13HiFT2ZkwnL!1<9|FQJvnfJ#nYime2iTu-v;Ayec~k96d}li+z@`Ikw|V4lh9ch}3Az z)Y|(r9aA2h2+07h57<^OGmLK{g@Rmh0e7JWjC@ zlC{nmJarV3jjiXoW)T=&HxDp_xS?t<-k=c9$ir$Nwg+-rMhv4d67jvnl=E$^i&o7 z1HJ#YG#WxyBlq{#FW}h$P$AiJTm?GQb*K&MBH|$O?c(eVoN1+40_@_!XVu99;m-mr z&YM9vsbzx%@(V?@zPnEW7=g3C#Jt%;H-=v_mSGxS$L52y0J7^5L}U)h;8k)V@C?a! zkWa4$F*?YN&GLYh&PTW*=XQsReVFQVCziYtewiZ=A38kWK@YaVmN^Tycwjuc1z?wm z>ww0~;Q^#Lf~fs9$zy_PpYPH61w6Q>sm&3VVVQreX}pT=Z(qLrMJB{0CZI|XMAUY>0=}U^IG;@4nA{qh+|8Doz zAW@^*FduKB*a)s>s_p2l9BJ-h?-9e_J=l!vvsm4-23ZO#csMoP-3x&e)(cDm<{dH_ zy~;0_PfR$1D1(auX^0R&KxjdH@8%39iVPQN0NMd}qY>c8F9h~Yq&0#EGgJ1>43rGO zkLUf>nOxxHV7R;C0nQ`s62OAOGutv4VTj3LVaJd#E#x~Wg32rN(5I~Hm@28c z8F*JLBwP}J+F%v^UwA%HZXeQ`pjk25CE*+%!~HXzlkJ%d5{wvH$|>;mAVDqh1eI0HeYlEbGM6q z3+m$6HF^aae3iS{P1VA)xa&0lG|r`wdoc4UfN821NsQ}|lH!^vj<~*D_ct)FlR9AD z7CIchy0UW!CaeYV_e#%$JMhg+P7)KwtD@$m1sYA5ek0q26ihktGTE>D{Kf0URKS~0 zJ#`X+JP@f7u3Ns(2Fj=!dQFEfxG#eA+a7MVrw<$-i7-t@cIi?>)p_b9K`-W(r#=|C z4R3pTD)1~FE<0{6Y`>_?okXGI@0;sad>sX_PeIW{)AiBVhj$aS1AYuCmC90;_6 z`!L+rDT8l!yhd;(qFfPoAbYc$_RVsR{@Uh=QP8Kq-L5WDi)$U#PY<00#shf{n3%sL zQXzMam0`1;P6hPcbm?hh4a%QiSe^n(ehqLf=haQb(33m!YqR66TaC{{0wleu#+*tO)|sHehAnwhjA9REk+pL3|RxkTChZ-n3_WrDr>q`}1g3WnwkQ z>JNz1w-n+%t8O}B??Zv(6_pv+g2_)=eMtAan}iUT&u!UYWAfMSAix45~SdRd0GB zo92stTmL_|DZv6zW^8XF3-A&F%3DkNiH-)4lY82UV9|8MZDaNY`mg#Vg2hB$M7D?X zHB)!VHpoPR=l6BS*%}cKth$9~5Iy4-mf&Xw8mgV>8^>w0LXg!Oy1wpns~*^{rL`KU z7nlr=QVVnybRwM-149ft(Z$sj0tedr{jb0u#Jivl;3OlXpg#qYtEqPY74P1*wNF3^ zata}Z5&pmm)DqaaPVCj64Of7oISf~FrSBsv@$edk*~z`AizyCknXCU3YL_tkKJtP<#zF0Q`}FKGvUO^lZ|Xa(r07qEeSl3 z*#)6OjNX62>)Nz|fm@d@-AgB}Ro0PhWMkF%!j&M<2ua(JOf@w-n_5()4_Aff1qU>* zv?$cWL?=JmpdCM0fL0$E7)=+h2}|MhP41q29&W}YzD6IogF5WLl8W(W<+5%BC=Vq9 z0PW3F-Ag)?0PjPZS~YE&Vv||AkiwpvnW+X5WrBXeIAehCe7LVQA%TOR-@Y;Sj@Tc6 z{DB{n{tXpuv$3K51i*6#_Y83=Ad9-Ulfm7(;f`mlrw(|Hh~fcqZP;hdHAkA}?CMG> zFB%!KgZLHv?c2W};>C@FB@;Y^j3btL ztG|2V#rSX^Mb~&d0Bg09NIWzT$Hx@;@@0I9=dAuB%nE7d@e$56Tu_x6nv(Z#r-13P z#Qi&7edcGwZ~@MSU&pYLk&x`v47r?0;ZS4{h?Zhh2_8}d5r2Y|bXJ-ri#hY$KvYR( z<#k%WQ2mj;+gm7<^Wild5NSuQNrv|=UlnS>KHZAyT z6dT|QD_>okcb=9^|57bblcTP!9R|5Q>|8(c_J%_tLm0c_x>FHVu-EQxdcL^hJ1IVC zFDU!CWoQ@;Zby1VsPJdn^m!>MH00VrZg3dijtB4#vNvMh9mSn}xSEF1#s2|bg!a3k z$$96cxjU(l`xgfxVaR3H?a$1}AVC4ikKN{2EEcYqqwDgaVD8$rYbojJc>%wph~67| z>f$ye&NcERZyj=W6!*LX2lsXhxSb7S^3OBH3oSYVQr?f&VBAUP`T3DpKT^6I<}8tR zQk>c7Mq~90&h%jgr8JC%g&wurtZMXaS()+j@^Z+bN2MzZw2(M|W{)o^wcB8Op##MZ z=ToC|KR7HE2AiXW#GjX27D)o~YAZng(W2#x7 zM92Sro){#}JvL=>vp8niR$C8P_|AOUSdJ5XPU9|umWBy$z$3s)Nq<@xt2h9?dTm}X zmgUyvozIRSK6iKbkhsOsvaUfLO-+UHa6gp?<5=S=&PYnR$8 zfKaLZaD_wV$e9y+p}I)7{vmt1aqO#BsCsBFbn1sWXx^y)3pd<%03CE%;A=UDr$h3NQvBHQWCg3NXAWxY_LpLoG-V=ATLFXiZGv>=HzW5oCb;_$it5 zDqA0oPG@vbO>EkoCGwf$dPUW-W5=LE^a>=Dz#r%xl5%xjU47W6ePztO$|vM9*}*kR zii`WSTfeEP39?`9_MEGzQoA&RL=3QPVm=;aCljF0`{kP2!-`6gL7*}+w!k1XmS`7 z91b0e3p3My9-Wcs)@E58pAGT$T}qC9eSMV52mX&=Jhrs;^(})+6i`iRWG~>1pd=ao znqs0)1VP3vR;p3?GUN2vxXxE7!-WzjSjbzDKsBuY>hZB*%RRBxC%Fy=Xr4O0VgP9) z%J^M_4j0mVAQLBV9|}+1)U_8x=oqgme=ipB+|T6INIFHUt_n<$me$KW^Hg>~=JM}L zd-jR9n}pc{m69hz)>V{r`0jV~n90o4R8m2KE|?JbgJe0yJ$XNNfdnq;hxOzGH!<9n zWmakFZ?sQCZ{j#AnDS4%NQ60NVeax9;LtMwRAD4~p;~CTy|5{Az7Go5!9}1>M0F$C z@>owRt1qM%hi+u(#sO@VfyFN zKDf|GdL@H{HjrVTdYo@{ zJCleUuL0nLOh1IP5F22uWxZ&SR;#Ujhsk(4Hkr6F_(X5dqF&>L@tS{j892KeOcQ?EGoTJ>-nnIWs8en{GRN zNa2RMsp;$CLZ($ijJf%jUdPW~ojU3I@sO&9Eh{K!n_1xE~hSm{sxW zU(0bou_k~|NLl<|_JS`aoZZ{>k^8(ZvAzKk#|gCydpNN+HjpZqXWu1D)zttM0qNLU8XCgg3orkx*$~5= zhvHXW&9t<%R}Q!@At8qmh!h|Hc{drZLqej+g$pM{Pbd>0{haB7!$n?RUXoc-a`G)V zx7oPY_E3kPjri(R2~a}tQ!B$J;V?+jqqzw9yl(=;c;!A6BXN2|GXWv zEvUaXgK79bk;)vTKua&=Y=-oZ2TJ@GfHp>GHH?dlHd!HnQ6-n0#5<2wE6Hq z_A^T-K~{1^Zvm7A{fe-Rq5Hs-o1DPGk5IutPgRt*&?sT%0P4hGbIe!Ah{E+&CMF+v z)b!qzs{kvixedcrXDkzCKOgqtHLzVi)A*DBzyc!;*7uy1!f7&e&wO(97_p&!< zKV(0XWE_;TAqy#C)gujlZw z8 z1~p?jug0oEY|1U4_x1NvJvQz{DeyiB2?wnP1x?tl(OK@JySa|;u7=}aT-MKmsd9uu zEo?Cmw{RE=WLKSJV$yrNxqc>h{ecTrigfv|AoSid=huLwq9 zz7U_G>X*X>K%4O-66voTRS>1MmxD{Z!5F~EDLj`J}FaTs8+ zslY-Y#p{OqQBXz3um*x)W@!uIuyRN#flQ|Z)Zii-9x~)d_?IFhn)GgqNfRM2JZl=n zV`5?g4tp_`xvmIKtTvp+0-3mdOVeVTodPo8r^R~cs|hEgNaB%aG)qK0$YQrq!c2vw zip_RrCAbkJT?P&nxaEl;LcNgs{v2N6Q;(qz@uC0t-PPsU^kJ!yf(pw1ZCgq6K)55P zCRpGW7Z%bS5YHD3Bnb{mTYnW4g&e*SS(6x<&n?J&S*7<_5EQ3g86$3(`I=zUBO6`yJHG=4-B%HWXx;$);hG5M4%fK-3=KJIh_JmVn z=YCD;@GOnXdn%7VdmNvYbqgk$K!GwaT;JOt(rVIXXwX6 z-Yqf0l5PWd0Ml(cU5T7EB+L)E5F!IcAaxb$Ui9san3 z<<-qoWf>MmMlrZYVEWcyn4q`^Ax)w}LT`YrfrjA^@&)VK_7?>NOb_Q5$)NQpK)0{Ai_f!ASgtULZ$RfrY6oa_LE_h|v1$PpOek7qSQ!8Wxa z>>*P)h%U%5=qYPw=Vr0{LQ6iIZ9BNsM&5LUIuXEA5c1VV>Z=;}J`Bn4aE;2t8TAPM z+q*I=gzA&@VbC2^Z-D%?=km;1Gb~7;PYP5`1Nc;yI2|3G8rrnJ@CAqkf*R8Ty%9hL zwjz&7<*ou+Ljzo`iDg%ylT%V`%7=*KjG;XtdGC2PJCtAt%d(E_(#4q7BWj$^RW!yc z0WQ2fe4K%ynqCl}v>wx==AGftL+ZZMjdXRbJcqhxBf`Tup_<)r|F`nr^0?i3ggLmm zYs7>bhFzgh8DX!%4I^C4e*2a!qiTL-aTHB;Yro^4&Z&qTPy&t-RN1CMwE{ImT$1@g zAhp!H7`TD;mtQI(Gta@TRtjN;qOqKpM`6wmS^f%uC|wq)u(mQ^U*gS{0cRxlLA*xM zo#(N(y87)s=h)z&jlVoeKalF~VGuC1S_rbwWx@fLBFCtdQ^r_x!3Bx5*z-?g_4H)m zJCfy=yHs7nUj*!bbD&P@LWq*G<-BQ4+~w?s4|)0S?s}tm68aPhhBYMd8FDH=FDQd?H<4A+{UZW0CD;~b z^2^|m0XMC!il}v*r%cbXHL=08Or*mvkZp(@F>+esGV5A`B{C7jEji~ymynwkp>*j5 z9~L>6bM3_{N{qbO*gvV)x`PMmx+}Wh0g18kic8Qta)Ur1ME;{#P);9Un@LGZ0_XRp zbK{376#b{`ku121kJ`ZR$WPceGhgAu|9=_b|4n0xdpM+|q*~hA{-AT&XTodZ0fNnY z$$|-SD)`*(pqpQzX`rba463d{aOpRuqVgIUxU5U7wn!1&Hx-zgVBqRkB7r7=rJi+XsL$M zy-Wi+JE0rwcM}lC8_AGbvphM{mPiDp`!y0lQJJ5|k9eyd1GWRo-9eIx6R!@gIQ9NV zRQUeE!w`h00YEc@rn~e>kRAemQ2&TT)gdBsvd6U;&QP=;uGfP6GdL=YGP}4;n*0F? zQAO0@z`|Ty!9b@az*gSip^*_n;3+tVaM{NQ^fcC!PXalE&>ITM{tZQuM!SXC!99RI zjif=fK)y>J6pg_i1m>hN1v!F>Qc5Y$ymn%gmwDs70-Rp+zfUW0$R8&$vs-3v(O#=n~xkKAxhb*#@SR0|5c(s2KE= z!^;(Lr4p_Lj(2WZ#BD8fG!5M4jjfL0)gZT?%(?BTzK$J zA?Yb3VrRq-v?Nk<4WI~#RuTGN(YdGRKAmHX@!e)-5hLC(6eL;V7Jm^lckWa9xx=O1 z%wA(3lS-gwyo0A2uwYnXz^7qXH4mI}6GRs5ab5H?z@VPCu7CWl2t>Yku~Z;aOEPGK zgUxMiR!sjm3e_C!p?eRM&@2AAP5EBhbRNb@KZyLw%e-Fke-SGF#lp7~hfbdG1)e?+3nb%&ma>peXq&HBEvILfZ=ZhXH=!rhqIyOj@~ zT6zKcL_{EmF&bgOo^dQm_qm*ZJH5s(!AWI3aP|i&?K4#F0!dvl7_i4TZSCwmIG3<~ z_&;ILjJsS^&HuJg1=SaA6>Az1dkxm>yYQ|EE(smHuwYMNEdxM!La!E7UfV9;y;h{! zTQFvnMvj&bV$LJ5c#T~`+qWa955j?V$oVt+_u>kP4s-Ri{{@EHfYe5AQG4@@|M|(` zu=5EMOP{2~I`2F&gN(p*088oKWnHn~Ebb=4;R$3)pcq>4J+rKA*u8sOuv9NqL=1N2 zjnnjDe#sc!O*3GEJT}9)tdkOGsjat0`$J3{oTpmXa>HT00P%K*`+C{CeD|L_C1sa= zXS}_CZuB+c3?s_r-MepMb_o&PCU5rc+owlG@~b*w2fBR!u!Wk(R{=`9&>(}$xB~cx z_1CW596FgsI9yduXdl1N_#VhyOob2vR1AwycY)Hk3VS1DdAri-X;pfDrwz`3hgnbg zZ=Xc5q&ANRg8}dD>p=pGU-TeBA-*QFE_Cdms6Oh1QD$0N?(~~~>8qmmakfy037i>( z2!8$#m^2Hdx*g8P%`?1p>otG?v|KyjYQ#}m{dVO5dEqfqLXQrcve|V27sMomp+$%~ zZ8sLt@rdodXATG$=(sn0FD0AGEjyV(>5)#&LRmJN3J$=o*h7-!dH^y1BPJCneDEM7 zLCm`9cI2{K2Od*?E2u6S} zBpqD)pVI)#FUBDds4G(0r|co3LV-%()kB_kNAMBf$LxPSC^R*>FA{S9Z*lv`E_png zzD4p)Cb?d*qdYtDCW_K&_LIFlF^65)KfRzz}W6ho*bnDnV zQ2YSGYr7ca(vuhsxg$Ao3Bdl=gs3P}&tvFW2~taC5pA%|QMmAW(Jt*Wl$hEM4#jXM z5vk@xxoYe4J_kV4D=Yrpm&2WW8691AzxB#QXuBn#+wjD}6wkZ@KLdJmWGHQAr3&oH zu}{p9v1oew$h4tCPYxrASpJ4&K9IsQgF_Q$OcXM05VhF^BZd(d=-BdeIt#yVuF3!? z$O4TrmPO<9J{W0CJZb*-jY>#4Gl!meg?0Y<(PdP1=4*xc!n=ptX($6E(zHa> zyS!Fj%)3+_lmEXfMzj)wcdMa!x{$H>jXKh#Yy<3D>N>wlS{(ZC1y7B}` z{!3z;V7MT~Xw{SOA2g8D5&qAA3gaIu|HduhoBXe!LaIy97C9$(X|zBc+#;$K{a+4Z zh{c(ysuIFnN4{>;o?Q+T_5Xq8*Iy||;92!fCG{`ndLdgV4-{umU?!O-pK+d%Zyb2W zwxhxXyV(|;YmNVZFkL`$2at-9FTeIP{Jsmokh|~_s=;(?EO_OAi@}ZX^!`o8e>)1| z&Ym6wwx859EV*GaAnPF9RnH+jB*^`g&k~5)kqQisrhk@znVBqx#@0jNmR+gpb9BZOGPpvxoH|0*v7Fzy@%jST_wQi zg{y<|K5%CU3Q3qu^#I`wDy=e@vXzRwU!Gi4q$H7J{`6=817=YTudq@4>;s<99tTmZ zKB)#QC5!Za%SP)TJ8WD189|_?H+T`QabKR~h5#iQSCkm74(1-5%eGAqV3Zbo4Jvww zXC59N@Q)uJcBvU4f(TBPe+eRdmS5}u(g3b3-};%MRU)C!dPj#m%=z>pN}QO#>XyiKhgc2`TgeJGN31>KK=$Ak@0oU{o~e!H}Gj4 z_0;0*!<^%%71ER|3=+&(U*aj`ZAXC9x)8J%a3gl0#Ir#_VV}G-hL8NwHK7r_}d zfA~=U2nMO(U4z&R=H(3`V`8Az=ZY7Umuo^MiblBm@Y0PPPVY^?3=rtmaG`$=S*MdR z_Vj)5!vd>9yEPend$-VDh!G91LVj;((FReFof=6?|00F+55x3b`Xl~ZsUQtP>(T=4 z7D6IE-)nR)eXrieWd9jL{R~j*ed$xWl_*thVXg;E*n6MTPAEI7r>Crk)7bj`C*pHK zcY@eYQkm15AB^Z69*O%lA{N4{-RFT3HD2dgS#E#cW}_bU$qxK&z9c1r#|SI5|}KdY~UYeelPhJm=mEb2nq319KZPG{5Rc$RqZ>5E2|b z_gDaa*gnl_oekQz7lP3IK}eMI!$R7r);dG@l7j1rcK%0{x#loR4XjpGfm|AdP3tV^ z73!oA32fUT=dHYP?-LM#`Q-cj$N`6iWJKxF`|)e;`swz3fjiA&-LBNW9?cCfIV6uF1@7ACx&RD(kN`;)<75 zFdY5j@Ulhv)I>4F%Dl$?-&W>&{`{h%hEvB2{P~k^kHKidOZC6pauSR3SdfbfB9`!& z63U#8SeWD`li@HJ_?-D1F+`xEqk}u{rc`0@RWZ2iAImH{c`%G}-kOs`Dq@J!U_cf@ z^dhnI%}b6~#JvL#H$yLx^zQ#pWAbD$Cin86*FX28Lur00{Xy99{2l|M+yHGA%+Tk) zyH4HM7K)zE_JCmR_W&FC+t}hq3^%+yO_a|^XoD~s-EQJ>48@^z0U}343aWw+x%l!x zazng}2+-^Q+LO~jAs<+}EJD#6Yk~LTLJR`7fjB8Y$ zZ5sf1ErdU`uk%MQAIk#wGs$}t4EKQ|!;*!QwkePZ9{Hi6y^}?7tste5m0r5Gwi$-X zn{I9X6AH}|f9{cOthS_J;>(q_hW^Www)FGof^#Q1B&cLWFr}~k091ju;*U4+o7YMLA7-Wr(2#^s(BojS{TA#?+dyhL!y zamDu2?c!_zR^Qs*E(cGn)lJK!J#pi|L*#-u5S4)hJtxO#Nv=)t3rK0kixw2dKdwug zvmWv@aohX?-3#K0TtML4SBRPjtU2AhiwL#J`RIU`^ll4vT5`JZ^f(v40UgcnVC{M- z=L9gDnWko@VVIz=&jKh6;_7Cn@FM(zLo{UW`xGQbjzX_TexEgRxJZ9E`z1oZ)FKRq z24^2$Av@mKXAFxLB0ThHP?u}!=#cI?Gr%E)3_6TZjYUD1_UO=GMsv45#f3^YpQU~g(@*h^sS2gt2p=h+gsLP03mI;^B_i8bFaBMc){L?{m{?Z@y{sh&H@c@C zu7P3;VoAT!l$&bANn7Fcwm}RC1G-XlDdp)qVT_@vtqq8J4$!p{?DUt2DcDaJ`0IHXB_WZvwY_p zU2cfy020mMyJU&7G4OayXCP!4s%eXpt^9WUKN$d)U+@on%!U|RjLxxL1qPZrqe48M zF#a70?Tm`TW7DtbT6vk)EAq(6iKjr<=Wo(v@&5jT(mr+2OL4Fobr1~E1G(YcH~T!5 z%{^9#EvW+4d@cdOvFK*OABPJr(s&=O6y@kLoyFh5~TJ2LMYb%Han$#z%4#whlwA1 zO}Dy>q+T+e+!xqBO#1UF6QNSdTZ2L5q@KhG4#;khGx3uP&cxc`W}&9WZ;x+JAHZiQ z+kT@dw7bH;I~lTvQ2G9eHbr8G+QZbzM+g2sQ`1^-0-8>aaeQ}**YkZ8^y`o46>8uN zXC+p?$)a7G0-X_O5_F8IzNhY`dEf#z5of`RFjEohd61|XK&S(P2#~Di>11;})4072 zNJQc}HXlhzC3}JY!GWIJ0b*;BDUiro1cG z+P&kD?dDU_4tO}iwfj?|{AVVDn7GqD1jGtyqqiSRHf-f1*W>rV4eUS=ntj&S)Z9d!xfKQQq`0(8${+>EG?z=nZmv7i&8aX~6{6mAE!SGO?X zW5WoUa}bvsX~`@iz;Tl2R{%C*vjH*?E$?5r@at(*QP}0mnQR<3{Vhxz@!2VMjXRV0 z^IleXl+5S2O~9q;#+EPQn}Bs15warYJxPw<71+h$bH`oqT8F_FrX5pFlrP3(O_0IA z3&VANSBs)4HIJ#@KNHp1O+?CFOjG`hv*0mczM(~mAD zZs_fhgO|%&Q0a)63!8fha>zFofLb?#O#t#UK%CjY^2O}dm4HT87|Cit$7wO9_iUVJ zOk5mrc^Fzm&XBUm{aGM_)GV}!<#7!RUm+D(UJ0}Ou!xau4G+zI%EMRdWn|1XTqgd) zT2=4}Im@qCO^j$ln+%G<9%#+SE$pm>@v|ZW-EW21R`ywbjsx$R*u{Y6uJ9B(v+Vcdaur z-utudXM+x)odECtm9?^oqd@YEPZ&7-uzj{^Di!c~(VL?Vfp3$^;pF+?_{Y=a*O zGqbl6;t4^_Ne3@@6ArDbb{<`1N;C4F|B;Z~Z58V)phS%$mKln{ARMBHEdlfdR@qrV z4+YF$H(WrA%YufFkMBcG&A3(w-$=^z5=@=u^}4Sm^~c4(?l|ykFFQKi(U|ZQ65T1Z zuo)jX>0bhZx^8>UmhWhe!{=a757Q85DvgVmha3sBK@SzN0DU!@bN)hC+PX zhpV6pW7eERnOlsQ^gxXpgV?bkT2Co(5irz0rB)bAL}_8Vrx|9JQ|*PYx(8hA|L$v) zNphOAYyWxGus*^)zv?jvRaHTH_5sw&6@GG;(@;A6-m}f`jK6*T*Xp(|2?)=x)h6H!2n?7>>4+V9bLI@U>x7}VF`0Dlaa8l4=8akxO#PY9}V ze_ms?-&<0UKB9(xWq`Q{VsZOa{22G-us-bF>b|&fzikh)M~;6Tr2rmPa-Llc!^p#} zac!M`M_CdEi@^P*nTD&>1%nbKaLF5&iKIk4Q;2L4Ff_T0mb zsi^Cz?#0@0LJ`*@5OJ@mCPENAd#R`2%pn`3On$XR(I6YLjwnsv`seR!U0Y3WhzME2Wfby$duvDb1W_>GmP9s1WiP=Cj5Ll=6=WkX z9=NnLk>4r=t6E72MA2EubaI4j${u_OqUko-RtKSB2MTm4dH-J-QK^4G>>u!~p$cB* zVI^13ov#tc>R7acaFTiN{)n)TU#TP6&_)bZVCzIrFzynhHY+e;m^`k{KU7aQIIZw3 zJ9+A5Zba!@B>*Zw&`oD1ub+A%bq=Tkq3)Aq+WaT_<$=QPBs4H!esqa83LhzQ!0K;x zNTvQgB08Pm1IG$Wuqr9VksLZ6R98iLF26^O=efZxu<@8tMx;A3y72A0K8PMVK zQV)7nKrI7XXHGk?@Edzg!*77{=-)8d$Ax)#uuhO#Kp)h<{5gFr*b1r!WJlt7#dLP; zWma%YTzXsC(}rlIiPWKl(?BhyIU3%|%7WIN*<-2v9c7WiKu>_y`!i=Ns<#j!G{9|# z%Xn3(_S1)sqffSR=aOIT)e&xb<9B*xf3obX$_AGeU$<4%>yixz@F?g4g*HU=2To)x zKG_8^54%gi94zxtral91S#rK0lSl*jS*yeP2UvGtu?8L``r&UkH zopLj>$)FT$cI^3mX;$j>L0&vuHyn_8ib4;pNRj{u4ZU5E3S|G|6sK?OndR&oTes%`bVQJhH>esNBwkl7w#eaQ3 zt`2cETf2nygk-hczjg--{@!H!V0)cf1N%y^yU1$o;ib zLH<>JcqB^=xtO0q(SrR`4;UBxOS^m?sdG6M2Ido^6UdencU=Ggfr2!8s$k&!aLusB~bn(!L1 z#=vWF;$SU`F4u*P$cB-c5HW4K1^!yxvo{EEaAZ>1;hX(917#WAZoGs16APESDm?f*9^7`p+ij@fDsr3!Jzg^!2OQOF_V8SNmT%f z9n37CjKzC6k??osl$HbHaX=i&Egb0w6@cLBj9m!t zK>tw;eqBu*FHKM76>3KiOH4GrKSLaKA{A0|`39>(S(u6fOR&3S{%?BM1yQdJY&rsQ zgNC|#CRkS|&a(&^i=0s^#Ed7zN46&*J^fkKns;=OIlndEWnGrdI*R76N*1f(T;3~{%Z^PM(=v(Ba8@R8GHGbX|K zoBQ@gMM)kPtsH-~2p;M+ZXMZCosb%K{X^*2>F{r<-x`LBuNmhe-Fsj(h>D6@=o%IB zTT?N~!CeF0P{sJG6b_?l1zP3o!oprwx*Jbv7iyq!^4QqeNOt1ugZB=c2^0_uFUPIx z*1+}|sQ@=~%;<3z(d!P`STsK?zseoh%v~1kQn3hn?5g z)@Z*3Rh7Cv0xswbT06A}WX+7gb-}JH@k?#0d7LoP*zeNl0Ol@8EcGU8M98?jm~Mjt?L-8IO&^d0T9P#=YWxxL*gF3<`#H4{B4lwXUf~AUYp{x~lM*Zc>(DctX-oUGW ziA$^JigM?z-y#Fkms7PbXAU7 zASoS+Jac^o%TusKScafByL-Wa59&g#$-NSP@uaG88Hm+8M`_i%9-gW9b$btv`~-l42V5R~lzhU|IoR#1LKTz+{4j);2%-r@`~?oa$WkOjLqov4k;)t? zZex1RM`yVh*9XfRt0RdBJ<;X-!Q-y@D4k#s=MHD z0%g%v_$l*zG(y4Vn`JH>ET5NkhsfL<5@rIg5WA%%!^BqK1y6>wN1mcrsE3ChLPs@RM z@;yyWI)5T$&sR+T;{3ea%QhHBJg~5!25rrVkBd+&RiZ zvjncqoOsArR8vk!^bC1GszG+=NCy(Ip+xeZHi6%n4Za+KQFKgs4mshpFsKqyHb!;n^ z?o$lKWto5+z)aqZtoC{6Vv?blujJ&)5}B%9sZq)O8yRuzc#V?(q|@5JCPf#}iw;D- zM1BlPwI5_?+}2>;aUUEX8m>s4OcMsFPFz^eP7{Cqfztb78zrU7uqWvzkrNwnNSUFt zGjE<&ZX>VgtUzHl@++V?nR8`SN5{s}`afuCZB^CN3;z052e|Pe%YvD@Ubr2ps4J}H z;eI=AplKElj64yV9uWx7ko}@ne+FH(-^Kys%7;pQZ!AdVRGR@3>Ml!Y~ zB~MN52@elnY&dLp^wxj=jGh0;#mVUh`>nn_xFuH%+S2xln@QN$!_Gt14JtDU4UO0Y z7c;)(sFak@XV1`aaB<;jyt%9&Iv!1!V5IzaKUWrT5 zGjSin<5=@mDPAf{B414zS)Aez3=GJT^?z0;U~(|9<-PZvfsMt1{L+%OzRHIEO@ULp z0=>SPTb!I!<*&MXdg6i$U@@b?uM8H^Ed&S9Vt}kOo;KYvoG8aRPpgsP(dS=@_V;*=cEM5vGx1Z_vB93Vp{O=Q~n8agy$h z*3Q*ri_wy)d>(hctB4oXFz$>YW$#7hPp8i(nOQ+Ag%g82cHl%Uzcm6+$xxm03grfV zqvWGu-d*PK=%E+vU&I~Q<)|a<8i9dcwTyz=2tA2h#O*4C zpenC}l7u)S@*CKW?d|OYTg@RPZ_VH8n9Yn{;K}y%b)1IFi$0A*c3zt4{oYerv=0h# zOl9C;XIIur5P?1PtSUUCGqbb(-@b(cXxG%#6llc&HCdUAT~ zZVMYnxfZ|r4-=`ZyE-`$>g8+cZLFL zc-yIL_H=m+NUy?q%&NLrcBB0TpKWmhHRZyJV3;nR|8Ha4c}IDQ<>ktorW10If|kT~ zX?(Kr-K`*Enx*lW?vL1Uz5I~T8dd+wvFv=zS4D!ufR?6Tc_&)bQw@uW@Wd^s8AGDc z?%lihqeAn;XOr8|X|TEg0cdW%`ZVLMhEB@*iTk#IM@>G1FE|%ouCSkC_a}1qs1KLw zg%=P6r$Nb)5%*Z+&x36uqlT8&7q=x`GpvN?lqMquWNqUog~1ox$gLzu-mJW3h`g`E zmL2$PV0zZ@>u!=14hC8VbzJ)QojvkP^8qak>(tIN1bK%1&4ir8;d@Ta7F>#RSxaHK zgeu2!!6CPgHtoz30!4~ec|**E?F`LmS#!2*I+RpZk;1Ws z{x8zbhCk*g*=~Az8uoKb!Xw+MgpK5cBqRX4VL)CcF1%%f3}USWxw#4W?U^Io(qF#q zw`{sPcGAjVOhjMEQt1P7iK6CrY;sSR&37?2UD!wpX-rq;Al9?PBl@!6WH`6ZpW8#D z8(m4vWTPEux<$jq^5vd>G_yZl;ZQ|proAK%f!y`3li(W{dESIX*15leOTwjVX48C4 za-ySNNP3p4GN||-uIUH0`GQ1}3bGPT%y)hiao{Oek=uL1q*X26Mw&`fR_m7s9gzu7 zqU(1}HP%P&LYcxPMOgHE)Ij=uhirAMjCOkdf*hBkk9@uo)xJRtS@m0sA>Q2}(+U(_ z5~lUq;B01N|H-<#SpquYgva>{V!e=FcnIzYt3?M6HMh3X0K*99Lf!tp+mAOSpK1gM zX&3Jf4bWNUy5mFna9-)%s-f#{EhWvE8x|Z|vtUN5UEHwgSK}^RIEvjgR?HKO{_PR3 zME6LYf;zs_b!q$G^IiWyN{^1llTa9R6Rkl#nUe6XL8cjg(VG&b)~hp6`B^jS> z18kbq%yHkEbJ*H(aQMjPIyweCrk@+E92_!kZdFy+pa522mB&}TXJu*G0L$)>`a7Et zybjXy@^DmDRnhz+oq1>I8(2@!wp-w|#Zpwi*t-APtRsk>3%{I>DKMfxn2EZ6)MQ;| zB-PQ3)I_1hFK2}LDw>Pf>%b0@U9*H|I{jpnj6N1m#P9HUcB~5B+gS)OOUN&O-ey3Y z+veIezx`9LSgEWpfEOrXQE_olCIS}U+7j0DTL1io3!AX+?G2cvD$21EV?#H`Is&-> z2v416@*>^_B5a6hvkB~HLPJC1$dpeqrW}MA;>A;DNy&5Xa&j(!J4Rba$JRTl_k+tO z#X9$Zy+cIn9b~a7%IJA2Y$?1&3(+mm>YB}{(vqV}X2E-HMZAOZ&7fLFw*zlDSz$gO zJeDtUDW0SCooJK|4ncxE)E*KtQ-P$}R9dLQv_LppxB}5hmLpk(#!UWbXd?xtUt8## zIPs#UKwajf8~KkPtmtxb5lSPSF8~>&M;!&QRse3?I7SsbyaUy{1wlx(Bw?Q|ADPSA z_{$eB{z>Sz;98?)X2t?Za_~di!;IK+79_ew-VY>Dzg1Bz+{RYt7fO=kelHMRx<8rH z3`rq4XpCdUS5y@YNq)B1L!^7&@qM+K6V2qfC!SICi5!l4wgYS&H*o_mRU9{&+zF_rQ9Y?wDjpOXfg`;oV#N=lJTVNF(iQ&x*g;5W*5;O$4SXi z>)nO|+sIf1kBI0cq!b9fv2k(o+cMy?g5;V3m*4KBYlz-t9P58D3c^A(TilI*NEShnYTo36rP;wHrrc>DtmP$;}>*O)rL ze{@%`c%2C^KPA|ap;58Ojt5nmGgLegb>E@|BNjY-{AbWDRIZuSIh>UW-n=UBKASYa zde7!(w0L;kSo1Ujl9E0hwtO_ayhMPSn03f0D&he2gA{@ghq>0`p&<_~-?p6U>vYxTcX^zG96eh&58|Kz{?ltT^hfhFdr4I@zE{u?`ynGa7+<1w zFjsZ@hHIFwLsIf7K!Uj7A~jGm`%doY@F~Uxjfp%VV#>8<1+@L|8$Jwd7`K6}su7r1 zP#|q#K@Zo$1uJPMdi3Qn<;o?PAZS$@P!`iuZ*doX+`@t|-CPt3)!LuZJPNiAW@AX0 zD&w=ZmRzM=J5+3edNpf-_sz#1Z@l<6?V+@~4?^-K4_bw|B=1ncTOAmD?@?oWfAr`4 zO#6S}-7+Ih>XQV`B~?+H*fX9j)I#dmV_7*WunbB3kh6 za9A7Xg>`qs}$QBR}vO z78A;EOJB!1kJQE;-rLDjl0H6SXzAJ6=V4uIWbixU5UKG3xFD@uO}#x0Z*Nh!r>t6r zhGAgas2ds>Xi2XVOPk@BF}U1x6^)9C=@OJV^f8wpOPC3nAmOHDvHtnOD7S_T-k5If zBkF_JoO`1~EZKox(!1{?xV%;?NY4w%-&$Jpwg|JHunv#IF`_&^8r>EY94~rQO-h}i zTQaRWzZZWHz5UsPI^*CfKK{(Exe&WS6_x+h8#lrZ4?Vc@-hr}|Pks}2ah4qa-{1h$ z)FtX-Pays0fb~X^c_*=zC`4D#U?6TAY&z$k@9eTbaS{<(C+AKZ_1f;|l_v@uNL`Oa za-RNYvy5_T1m#YbwtV+1%}CMuo@@&F%fyC^5q`~MmTHeJ?~o#(P7*A4rxQMWw0T5_ zhgk;6NdJ2E*NF+1ay#DZVUJ|k*C#4*VfSLx2pci>%*@P#iK>{$NGdj07iQF>t)_+s zG`>gQF2=OeHaDTe8Si&0W|WgWCzaWcY@&yc8PII@`C*zjeL4Rn7YLc0bt(Si(U<%D zUj|zxLM00!6CcXM5T*>wLHKksa?uLbnRKliUO|VY+RdDpRRC86+qDa((e{6PB3d}N zXcidAX!0T;K%vvY!NCng&u@2OQ?6WRIQX-u-n&OtZj0#$CT~`+HP+lv&}EjS^W?K%d!{ z7C$|@pFvhNOR}82fpoHd@1q)^bAQaOxApZ}MfMdwc(>64b@5sbXoD7Xyt?WjjQ0)N z6Wo=QbnFrH=uZw|fLE#rfOG&6nJf6qN%jCb%Cv;$4w8vlj|nHTAzTL-w^dA>yo;H+ zM~gsMV(gIX;nRF>HSAKLn%*^%W-MY4JV zbrL@SJUnHF1d!@;PS?*tm{45XMZkp%jn6~J7qz@XwQ%tIS@koYl-%3!+rHyOP3^lo z9Y8trrwuE+~P7Jv_JchZ~9qJ;QhABibcVt{kSw7&qCL#qi0In*2* zxvgFBaMmiP;>wLRsVAoZo+}2ubaTpmGA(TpcP|+knK#2e-fG(R_JwBWVgUOiCs+^N1yN}-xM8ev&L z{->3DkR#sqj8@RSrAQCw9NLP8kqlwNkaSDIf~;JIV2%s5Eh@+NDx54Ig`B~g;^M}7 zqpQ0YFI~DLD|->fu53iKV9Jq41zJO;_f$de`HBEOs3~wOCfMMB^{L}6#Z)lInN__r zpbouVkq+ws;ts>AA}Ki+rpqFK+BHPy-*#cFWu3}dh6X!Ek`@6@nT>}s;a&pNhBtU? zq##-Ls|&ibQc7Cbf()uJVMR`*SEQZWsa-ex&Ve(;N-m(AS2ejL&&j_pCr4{){l?-SXc-65KT}9gZSBQ5coPUI zD8gZek|OSFq?N+T&fWqKoMd4LkXse|`=s7Z@-#z+%gDVN`@zg-QZ9W z9`q9&+@PD(?cB_TxZCFQqXd|7sXk;a8(vKQctpkjK+FVWV!?04QjVA|s0}+NCT5^H z9(cxhkOl^(JfMTO`Xr+Yefm$-{CY-{38(Dd=-01-;D2NSl!qCMN7c2IGEq@cC2P%Q zEKr0n=)~ffA@`C+(0|wx)y%hqZ;0w6{R3uZ0wnS^JjCKVbWJ+7{zx6ZefY{OP_~4Q zP7CLpdgkJgbf4;vd!FIL!L*V*M?;hL)*C8k-8h!l&6v~_tl6i~dqEWBbYET#O13gZ z0N%Xs4~cq-FQD1!Fph^mpk{jXK7pG0PSN@*(ph=TMX&fYv5N_jXP0a|@s%iT@p8ZT zUbrXF6zb|tDg6Rc`e?as;YnHKig#OsSJF ztT!5=#5VB|RDwSd*v-R4{2Jq=Qmtru8v%v6KSxF1q4GYFPbv6{qx5cTup2K%a!wg4 zu5oLez=$g(>bKym_K7=QpLf1t7Hp|Eq-Xb`n?!cbva#l@I-f3ad=rhXu+i`iDwRB! zZ9!?tQW?9f2P!BMNJ_}pvlmZZ1*2bq=gy;E(`0VRZ+G`}B%nFA3jyn)gOu$Seh&G} zEUAsfdRy+1PG<&fH58dpaq@V;cSb$zp%M6zAuAzS%3)RhWD%!)kKqhw#1xyyBEqC4 zrVp~r<_X!jquD=e=_87vil@+27JATe6~E&3ZA10K1nR9oJ6j27v392(204m8I(GHr z$@^rr7~C=n=gYz=<~K^A7wArdidSRrvxq|&@|hV01W^*{el1^U@w)y0zFpsl{cZ2N zM(TT<12E*Ql!#JT=)4=eozRkZ@xJL(kqih8PC=?rQkbmOF!?jy4psTq{EKbzSpdBg z-dTG_opg7zxFc=!M%{6p9Nhh~J^)F-89`ADmDf{n1lnAY9Lz9C%=q&!pSSyJ##5jA z^xvfc0z)IOiQL>P1kge^D4U~I+j<^r3CUw=ZZE}eSUl_7b+vo}2}wr=u>~Xe-{efl zKQwoiaADmsEgjt(D7zF1+?A@CrOrjXl*4keD7|J;s*5v7-o};Z|CSHCrb!k8GQ=%4 z*OWWZ@tb(f6eQ4#!^9b*bS!k*be=DlyI(lnAl6_za*JG3QhsQGXLT7RfzvNS20-4J ztu**GCnVvOn+5zXhQ57Km7hV_8fv9;EqJ| z!GxHY#Pm#8!N!c{=FM}^?aL}DHE+##f?GS=Bk59BF==dtHR4#&y@Z4(YA|?fZ&Ck{ z`J>I3kdRPzqY^T8CWyPWLSn27@u1(be^+PZQNUFH$L!}F&&9KP=L!&!>hZ2VPR6>vW8$Qc$kSWq-ySj z$4dUa6+k};hJ|Ybwo>AFox-b`saEm(l1@Q#K^%B-<+dhN1Hs}#!pQL1r1|G0!97y zTkB+%Bz>?yZR_rC-ruhx3| zIhPJ=4{Cg%R|}^Q4F;GhSlcmaZ(vxe-RtCa_{X~5+t~&|8R=iX&|>13Qw~6@*|)l@ zEdIsn_cDI`8<_MS=u;A_-H{7 zJz38vc~mlitS%p)*JQ*+~?wwOvz@+ z@19aIFkFz6lQa7&r=Wlhx8t6M#@w*(-bvbtD$Y4}>5q8TCG^VG^Y$BlTe_h@9Exdz0rwLmF_p-JPF2AHT@jJ>%JQwcF3_m&S5*Vqy^35`jrpu(q}{04B?asR^0D2xmHYR}xZEUciuxNCFH{s3(+D_69ZwK;vS!=!U}HbnRL2 zK94`Y5))DDvAf#OljgM*#QJcrogs}%RP@Fa>U2+Ze6pallmJ(B=PHc5LKNcJ+n<0* zm0!Q52CJ>b!-um+Qz$Xu>OKDbQ&)E#9BsbVx^f^!cxeatZ~R}%ZMiZrF|h*L}~9OT}}d=yMR z6kvhpw>ZeA_Vx zZXmSFchuCPWoQ(kDXkM)5(ZV#nymc6Mif{Rv-N8pg00uU=_hVdR zV7=28Y)`^r6dNZ6=mvOcpF@KVd6x2YnldXT=LR{npjlC&;gtcHhr$n6#W2EFGaG$Y zhP92GYn)e8f}gL4hK8D~j^yvpV9&=nxIkfv9CLFn6=`3u&1RDQR^MY8uAh!N3ADaB zfADBc&G`yZJh-bL+qv?jYpuwff}+giEdbB`!+H^GfC7?BNlY?#I0G!UmqT790g+*D zVL_sBv{v-)aj)-bz1hXb{pZ8mh{{L1_XYO2u&rQH0r2YYl{tTiK@>l?)WIPEi%A=yoihvo>|NVOy_()b7T5vi)k+rpDMF=bX?KhuxBqN7xD=F5Jb0~<2FrK6e5e&bgC@UK|&#CEE zdbE@o@jy^!#+io3kW!p52vcrTU>FG@&PWJZnOj88BgdzGbdd9Xf%TTu*_tPv^~WK$ z8s-46ilL4j6_u5RG^=6#r1@&X_$i3iV+tI1S2XkVE0rs{VHup4PZ_OFLKa$7T3Q64 zumGh6GfAb0o3A&wTAIH9{w(@qIe?l6#mY;L%DLeQG*hPHcnuG3xjRw&4O_o7DwKgi z@QUtUV`Z$25S~)N_?^v7;f`keByp&%5atDNHwPo6=^&ZHdki_Nq*UI@H0XlbT09y5 zqqZv_>h~r+OI8J+@Q(&(jtOwCbf4g1Qin-D2W92#c)3kmPY>~+@_%?V^{ME0zo{@8 z#=4dE{t&ZXK#&$l6u?Y)zn0J6I$$x*M{>mu=are+H|z2YsJRY3kyiVFDu+cxgd9fU z2#=&|5HHzmRZ4|@-Qbg#t{z{aV#$Ub{2qOboE})v#>K%LFEB0OcSyIzT_{R;Mlu2P0#OH0MGjh)CJ7f1bu8uJ@LL=rGE_Ps_jnbzH;p zod2om{Koh<->&+$Hrbz(b^3bRLJeX90)c>pj~TG6cg-~{Iju)n7^5P$j$#*#H8cnn z=?P#8Adsc7gib@Md?m3*?D^5V#A^3#`Z7H>sERaR2)q4CZ_RIbILGGOc&hRI=n|I@V7og6iX zJ_01H|HSzHJ|{JL{@f3U?y>ov1B-jfQ^(n)TP&=KYUzOy5i&r}AKlIYmQ&92*F3_= zMEudXKY8P*cu6cW<&m=Y350P3%vAIhVt^& z2s3NG->V+_1E8Xu6US_E`hD%2Om}FmRm8XM;^jv#mOnqg0B_e#|D0~?a(T=-7|ndE za=3e4b57vb^jv$)mC-F_SkhbeF|zPdEAb2Y%opqRC?Bga2YqTR^6(AERy@D(sm*59 zIQjUo2jzO^m~wBY$Xp;1vNw4jV$93Oq&fatiE+yZC{zS}JIIkz4JMm^+QI^vqOy;hqO7P9 zV`AvSQ#nUQ`c&(j&pJ$l8w>RUa`Mdj+teZZ}$UwOmJrH!izw-`+`PiGNaw;BOglC)VNkcc1lM`V3-lCFoc_ltEoVo0pk zHN5zaW|OLtfy5P=8CdBqJFm5!-E-jD#KzqSu?z2=rK0bQB7RwFW%Fed7$oyUgSJVZWNm~WU(>H&IS%-rv;%scg-)XB!(9kddX#aQBamF|E<`ripJ<{O8`uzhv5XdlDC0i8#RJa8DpEq+>PWa>n)e znjE4x{p)|n7n{9cOb5arhIX#sC#)a8ow<~_31JSAWZZjuntL+BC8vS=t2@^IyMOk@ z>xtDR2k}d(6>(Jk4hOq?3V&0krD};(KV3)z$`GKdwoZ}Xp^YP&EpT%zQvc>6v?n8( zTD{%+rqGAQFdr)+=5BUr@6|owg1`xQrO|`#n{JAu7E!F7=NcfHHAgl%482zixYb%< zjo{d<{K;VG1de^d$Yh4s4$wRd42(x1-(1X|4#r^PMO7I;{)lu;BPGL|Sy6Cz(?Ker zr=piAw>+gQ3x3JoK zlI?=pP{0Ao>7NGn&tu^YI|ql&XRhcvf%T3z*9S+783i#AxfdyV_NQ+^L!E)l8EFQ+ z7*q*yc8e;&`HD>PJ%4idzS)XRJ#MPC7-n%B57lOl@rgod3m@N82;EVDBte%YoFo&kxPjZa5Sk)ih|?zm3iNBP1n0(w_K z`-3k4emqz!z5%81XR~7D1RQ#mrkOzgfVuCLKyBTte?#{zV!E6_M_K0Gc#__%;Gm$W ze2j*+wu@lzxS|nxe9-I5KGBorrV;tG5aZEFGASJvDbkkM+h5Q+UCI^Iuo^+|Q6Sp% zKZ#;{0x7qC3S_FYvU>gmB90Z~xqheFjo9hY(D6iipZt0MnU6Zyu zEqNdmc2p!Yxn2--k1r!tD4w&O!>B_ST>iZas&Wscpo-v z%$}+&-y%~^6=5P00CFPmCyHSi3K(|AX9_JQ?fdS|&Gf)VHAXfTrKj`zUZRIfnI+_S z2kZ{U=}uO_3WLuGgvQs>vcXP5H(*bbwK}l-C9q?)&?=AHUBZ&N)uw{eF$-ysqmRn8SozI~3>x$h4^D znhGj6McY2@?qf^({Nu@w&cGNFS3_x(8J-Q1r0Mp!_f1Wk2Xqhbkdkv?qqZC&O*#4w z$31PqZUg6+De~ql$NiyftFnGw)kgn}xO6A(HsV1&vO8!_QOog)^d@Wcg$;oW^%LV zw>EJ(Ta1F(a{1Z?aGryIK|At;2WKh76SEw$?aO z!M<$qIB+!{wbMKVtSGk4_YCkui>(^Qk*-)N$ja|{(B6c0@=e4KYbgH9d6 zu~2eYQL2sK4LjCKt)L28oW92%zXO0#aXE3XDYm<|7Ebarjg9BmjfpPR<&b(zeY=!4 zZ+gMWX$OiE%c#UP%{osOP%VsdFKQZ`v9WP<-PmF%yG>PM7U@H-*PT7QG^6humjRZy_Ht*q*eAJdQra{bWLp50Xl_P*j1@xV?A+(&X`Fz9z$2G_ z-^--_FeJW=L;;U7vB_7iT-nIaUoq783bFf<vE)v_CN1UFE9EtV+B$|Mu-n0r8 zj5RL>k}vF!mT~)eHxhwiSU@n<55V23i*jz?eqLNQDT<%Dt1#SYF0H<$rC%a156kZ& z9~|T7_jgNCnJ={pE%VRiDj?3FGjH{g}rcxSg4h138c0m5QHQK8eK zZ2eB9vfA9(BY>l1CVf=m#XvH*MlM@9PPxxl(IddICx{KxGFkpJ`*)xj;oZ$$9vB_i zY*x1Y3XtAIB_|_V_c-T&=lS-+6JULUxZHq;Z`|v?aU-+03 zQds(G4k!!v|4PEJMRw@kvc0%X5=wub<0X#NR6o`%{#c`BOWMo~4GXd|3-Sm-GAz9c zVRTzYk7xpxD{}}HYr|#wk#lgc6`{A`@~o#vtGLh4QqyRg_;9q924Bx+8;QIyK2^CA)G`rtJ;NF{*BKD%T7 zyzq4Mr(lI(<9nYx9WHchm|HbnxqBz>5y!K8%_3T#Bwc9GcYEXdRYXsxd{$g*yqoWc z+G#Nv*##5siUd&`y9=&I+|3BsmXB`*$w2!18R`!Y(!78RS>rn!hIJ*N;QH*+cIVNj zf^`!uwvwKPfJzrm428BwW>JwuZ%Q{S7BBnj4sMv}Ax*}8vbsB`l#C$8wN56^R zxqaKG(tID3H=I2Hjs%E06}V%BCTs6^LMxD9$ej&Q^ZxKD22D*=mh;LRO}7y|5W+ap zTFz*T%VBb2ZH1%GsA_(@Fn3`V^9VK1(#9nwCNf{HPj#WP9@9!@kI$vyc3%snYiga= z3`GTn3&(%WLgJE)fYTqGpX#Ur_0R#c_4+-*&AxglL6X1(@``e(ejtxEZGUu*tD_I4 zoj}9lGyY$xt9%s$#{x*_4xXv(|vp3ZaPJ%nTQ znyvW&YJn&`zOJpEyj9CfMY>gad5j1S%vA}jBk%bQqhOxZg`1MweTy4DcLaZEzJH}Z z%i2BZ@QWqOh+BAygi}NFH$9IkXTzDnJ>A|P$Ib$Rq^y}MM=knRf2_Xru!F0Yo z(sAlbTm+P3?@Npn3+KjduI&0Jf4*cmr^P+R&CSsJVaQk`g&r_>*@ShI^-nO*ym^I% z>7bNj{?Y$%7G`?0goið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 literal 52808 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 B#)$v` diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index b01b3183..a44b3af3 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -608,7 +608,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -695,7 +695,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 27292328..07569d68 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -220,7 +220,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -481,7 +481,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -534,7 +534,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 8f3789d9..81943bc9 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -164,7 +164,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -216,7 +216,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -490,7 +490,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -551,7 +551,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 0557e0df..bf8397d4 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -590,7 +590,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -677,7 +677,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 9bce54d7..723382dd 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -220,7 +220,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -499,7 +499,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -552,7 +552,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 0557e0df..bf8397d4 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -590,7 +590,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -677,7 +677,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index af8206a3..ec841572 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -879,8 +882,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.996567Z", - "start_time": "2025-06-11T22:13:28.973555Z" + "end_time": "2025-06-24T19:31:55.360025Z", + "start_time": "2025-06-24T19:31:55.338112Z" } }, "source": [ @@ -893,14 +896,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -938,8 +943,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -970,8 +975,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -991,8 +996,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1023,8 +1028,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1061,8 +1066,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1078,8 +1083,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1100,8 +1105,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1134,8 +1139,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1151,8 +1156,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1176,8 +1181,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.304978Z", - "start_time": "2025-06-11T22:13:29.282394Z" + "end_time": "2025-06-24T19:31:55.652507Z", + "start_time": "2025-06-24T19:31:55.628692Z" } }, "source": [ @@ -1188,17 +1193,17 @@ "execution_count": 40 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1221,20 +1226,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1262,8 +1269,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1293,8 +1300,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1333,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1370,8 +1377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1397,17 +1404,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1416,20 +1425,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1437,14 +1448,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1457,18 +1470,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1486,18 +1501,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1507,7 +1524,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1533,19 +1550,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1572,54 +1592,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1629,9 +1657,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1669,272 +1700,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1957,30 +1774,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1988,12 +1809,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -2013,8 +1834,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -2032,8 +1853,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2052,10 +1873,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2093,116 +1914,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2217,8 +2220,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.344624Z", - "start_time": "2025-06-11T22:13:32.341522Z" + "end_time": "2025-06-24T19:31:58.324104Z", + "start_time": "2025-06-24T19:31:58.321662Z" } }, "source": [ @@ -2240,62 +2243,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2307,8 +2295,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2324,16 +2312,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2344,7 +2334,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2357,8 +2347,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.166006Z", - "start_time": "2025-06-11T22:13:34.094011Z" + "end_time": "2025-06-24T19:31:58.533714Z", + "start_time": "2025-06-24T19:31:58.461636Z" } }, "source": [ @@ -2372,14 +2362,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2420,7 +2412,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2433,8 +2425,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.213201Z", - "start_time": "2025-06-11T22:13:34.210228Z" + "end_time": "2025-06-24T19:31:58.576962Z", + "start_time": "2025-06-24T19:31:58.573769Z" } }, "source": [ @@ -2448,14 +2440,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2473,8 +2467,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2521,8 +2515,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2542,8 +2536,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2579,8 +2573,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2596,8 +2590,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2614,8 +2608,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.535666Z", - "start_time": "2025-06-11T22:13:34.502099Z" + "end_time": "2025-06-24T19:31:58.762582Z", + "start_time": "2025-06-24T19:31:58.737160Z" } }, "source": [ @@ -2643,8 +2637,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2677,8 +2671,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2694,8 +2688,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2717,8 +2711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2743,8 +2737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2779,8 +2773,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2796,8 +2790,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2820,8 +2814,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2844,8 +2838,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2860,10 +2854,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2917,67 +2911,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2992,8 +2992,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.223076Z", - "start_time": "2025-06-11T22:13:35.219792Z" + "end_time": "2025-06-24T19:31:59.213739Z", + "start_time": "2025-06-24T19:31:59.210358Z" } }, "source": [ @@ -3018,8 +3018,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -3042,7 +3042,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -3072,7 +3072,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -3113,8 +3113,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.348144Z", - "start_time": "2025-06-11T22:13:35.343061Z" + "end_time": "2025-06-24T19:31:59.287634Z", + "start_time": "2025-06-24T19:31:59.283037Z" } }, "source": [ @@ -3135,8 +3135,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3182,8 +3182,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.448075Z", - "start_time": "2025-06-11T22:13:35.443091Z" + "end_time": "2025-06-24T19:31:59.345387Z", + "start_time": "2025-06-24T19:31:59.340713Z" } }, "source": [ @@ -3214,7 +3214,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index be783094..6434a3ca 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -291,15 +291,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -426,14 +426,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -460,18 +462,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -488,17 +492,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -507,16 +518,6 @@ "outputs": [], "execution_count": 17 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, { "cell_type": "code", "metadata": { @@ -524,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -546,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -561,18 +562,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -592,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -608,7 +611,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -624,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -651,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -680,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -703,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -716,8 +719,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -731,13 +734,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -768,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -789,14 +792,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -834,8 +839,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -866,8 +871,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -887,8 +892,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -919,8 +924,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -937,8 +942,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -959,8 +964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -977,8 +982,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1014,20 +1019,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1055,8 +1062,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1086,8 +1093,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1126,8 +1133,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1163,8 +1170,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1190,17 +1197,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1209,20 +1218,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1230,14 +1241,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1250,18 +1263,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1279,18 +1294,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1300,7 +1317,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1326,19 +1343,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1365,54 +1385,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1422,9 +1450,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1462,272 +1493,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1750,30 +1567,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1787,8 +1608,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -1807,10 +1628,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1848,116 +1669,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -1975,24 +1978,30 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2004,8 +2013,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2021,16 +2030,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2041,7 +2052,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2050,14 +2061,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2098,7 +2111,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2107,14 +2120,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2132,8 +2147,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2180,8 +2195,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2201,8 +2216,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2221,8 +2236,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2251,8 +2266,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2269,8 +2284,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2292,8 +2307,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2318,8 +2333,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2338,8 +2353,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2362,8 +2377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2386,8 +2401,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2402,10 +2417,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2459,67 +2474,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2540,8 +2561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2564,7 +2585,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2594,7 +2615,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2639,8 +2660,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2697,7 +2718,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 6a51e39c..4b548c13 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -233,8 +233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -273,8 +273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -290,15 +290,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -319,8 +319,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -345,8 +345,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -396,8 +396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -422,8 +422,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -439,14 +439,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -473,18 +475,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -501,17 +505,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -522,21 +533,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -551,8 +552,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -572,8 +573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -587,18 +588,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -618,8 +621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -634,7 +637,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -650,8 +653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -677,8 +680,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -706,8 +709,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -729,8 +732,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -742,8 +745,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -757,13 +760,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -794,8 +797,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -815,14 +818,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -860,8 +865,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -892,8 +897,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -913,8 +918,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -945,8 +950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -983,8 +988,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1004,8 +1009,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1038,8 +1043,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1049,17 +1054,17 @@ "execution_count": 38 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1082,20 +1087,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1123,8 +1130,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1154,8 +1161,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1194,8 +1201,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1231,8 +1238,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1258,17 +1265,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1277,20 +1286,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1298,14 +1309,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1318,18 +1331,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1347,18 +1362,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1368,7 +1385,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1394,19 +1411,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1433,54 +1453,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1490,9 +1518,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1530,272 +1561,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1818,30 +1635,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1849,12 +1670,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1874,8 +1695,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1896,62 +1717,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -1963,8 +1769,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -1980,16 +1786,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2000,7 +1808,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2009,14 +1817,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2057,7 +1867,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2066,14 +1876,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2091,8 +1903,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2139,8 +1951,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2160,8 +1972,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2197,8 +2009,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2226,8 +2038,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2260,8 +2072,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2281,8 +2093,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2307,8 +2119,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2343,8 +2155,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2364,8 +2176,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2388,8 +2200,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2404,10 +2216,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2461,67 +2273,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2542,8 +2360,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2566,7 +2384,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2596,7 +2414,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2641,8 +2459,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2699,7 +2517,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 0d19ffad..1f252838 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -875,14 +878,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -920,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -952,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -973,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1005,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1043,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1060,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1082,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1116,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1133,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1152,17 +1157,17 @@ "execution_count": 39 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1185,20 +1190,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1226,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1257,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1297,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1334,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1361,17 +1368,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1380,20 +1389,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1401,14 +1412,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1421,18 +1434,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1450,18 +1465,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1471,7 +1488,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1497,19 +1514,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1536,54 +1556,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1593,9 +1621,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1633,272 +1664,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1921,30 +1738,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1952,12 +1773,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1977,8 +1798,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1996,8 +1817,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2016,10 +1837,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2057,116 +1878,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2184,62 +2187,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2251,8 +2239,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2268,16 +2256,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2288,7 +2278,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2297,14 +2287,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2345,7 +2337,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2354,14 +2346,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2379,8 +2373,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2427,8 +2421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2448,8 +2442,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2485,8 +2479,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2502,8 +2496,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2532,8 +2526,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2566,8 +2560,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2583,8 +2577,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2606,8 +2600,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2632,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2668,8 +2662,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2685,8 +2679,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2709,8 +2703,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2733,8 +2727,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2749,10 +2743,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2806,67 +2800,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2887,8 +2887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2911,7 +2911,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2941,7 +2941,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2986,8 +2986,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3044,7 +3044,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 16908e20..de891a01 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -291,15 +291,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -426,14 +426,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -460,18 +462,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -488,17 +492,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -507,16 +518,6 @@ "outputs": [], "execution_count": 17 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, { "cell_type": "code", "metadata": { @@ -524,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -546,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -561,18 +562,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -592,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -608,7 +611,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -624,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -651,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -680,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -703,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -716,8 +719,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -731,13 +734,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -768,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -793,8 +796,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.996567Z", - "start_time": "2025-06-11T22:13:28.973555Z" + "end_time": "2025-06-24T19:31:55.360025Z", + "start_time": "2025-06-24T19:31:55.338112Z" } }, "source": [ @@ -807,14 +810,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -852,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -884,8 +889,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -905,8 +910,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -937,8 +942,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -955,8 +960,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -977,8 +982,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -995,8 +1000,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1020,8 +1025,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.304978Z", - "start_time": "2025-06-11T22:13:29.282394Z" + "end_time": "2025-06-24T19:31:55.652507Z", + "start_time": "2025-06-24T19:31:55.628692Z" } }, "source": [ @@ -1050,20 +1055,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1091,8 +1098,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1122,8 +1129,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1162,8 +1169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1199,8 +1206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1226,17 +1233,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1245,20 +1254,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1266,14 +1277,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1286,18 +1299,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1315,18 +1330,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1336,7 +1353,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1362,19 +1379,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1401,54 +1421,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1458,9 +1486,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1498,272 +1529,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1786,30 +1603,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1823,8 +1644,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -1843,10 +1664,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1884,116 +1705,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2008,8 +2011,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.344624Z", - "start_time": "2025-06-11T22:13:32.341522Z" + "end_time": "2025-06-24T19:31:58.324104Z", + "start_time": "2025-06-24T19:31:58.321662Z" } }, "source": [ @@ -2031,24 +2034,30 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2060,8 +2069,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2077,16 +2086,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2097,7 +2108,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2110,8 +2121,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.166006Z", - "start_time": "2025-06-11T22:13:34.094011Z" + "end_time": "2025-06-24T19:31:58.533714Z", + "start_time": "2025-06-24T19:31:58.461636Z" } }, "source": [ @@ -2125,14 +2136,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2173,7 +2186,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2186,8 +2199,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.213201Z", - "start_time": "2025-06-11T22:13:34.210228Z" + "end_time": "2025-06-24T19:31:58.576962Z", + "start_time": "2025-06-24T19:31:58.573769Z" } }, "source": [ @@ -2201,14 +2214,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2226,8 +2241,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2274,8 +2289,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2295,8 +2310,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2315,8 +2330,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2333,8 +2348,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.535666Z", - "start_time": "2025-06-11T22:13:34.502099Z" + "end_time": "2025-06-24T19:31:58.762582Z", + "start_time": "2025-06-24T19:31:58.737160Z" } }, "source": [ @@ -2362,8 +2377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2380,8 +2395,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2403,8 +2418,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2429,8 +2444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2449,8 +2464,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2473,8 +2488,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2497,8 +2512,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2513,10 +2528,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2570,67 +2585,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2645,8 +2666,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.223076Z", - "start_time": "2025-06-11T22:13:35.219792Z" + "end_time": "2025-06-24T19:31:59.213739Z", + "start_time": "2025-06-24T19:31:59.210358Z" } }, "source": [ @@ -2671,8 +2692,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2695,7 +2716,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2725,7 +2746,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2766,8 +2787,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.348144Z", - "start_time": "2025-06-11T22:13:35.343061Z" + "end_time": "2025-06-24T19:31:59.287634Z", + "start_time": "2025-06-24T19:31:59.283037Z" } }, "source": [ @@ -2788,8 +2809,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2835,8 +2856,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.448075Z", - "start_time": "2025-06-11T22:13:35.443091Z" + "end_time": "2025-06-24T19:31:59.345387Z", + "start_time": "2025-06-24T19:31:59.340713Z" } }, "source": [ @@ -2867,7 +2888,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 0d19ffad..1f252838 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -875,14 +878,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -920,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -952,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -973,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1005,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1043,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1060,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1082,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1116,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1133,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1152,17 +1157,17 @@ "execution_count": 39 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1185,20 +1190,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1226,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1257,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1297,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1334,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1361,17 +1368,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1380,20 +1389,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1401,14 +1412,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1421,18 +1434,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1450,18 +1465,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1471,7 +1488,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1497,19 +1514,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1536,54 +1556,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1593,9 +1621,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1633,272 +1664,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1921,30 +1738,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1952,12 +1773,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1977,8 +1798,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1996,8 +1817,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2016,10 +1837,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2057,116 +1878,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2184,62 +2187,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2251,8 +2239,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2268,16 +2256,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2288,7 +2278,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2297,14 +2287,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2345,7 +2337,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2354,14 +2346,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2379,8 +2373,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2427,8 +2421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2448,8 +2442,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2485,8 +2479,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2502,8 +2496,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2532,8 +2526,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2566,8 +2560,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2583,8 +2577,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2606,8 +2600,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2632,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2668,8 +2662,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2685,8 +2679,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2709,8 +2703,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2733,8 +2727,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2749,10 +2743,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2806,67 +2800,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2887,8 +2887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2911,7 +2911,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2941,7 +2941,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2986,8 +2986,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3044,7 +3044,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, From 3094a8b5664ba65097b566d09aa567356c57a7a7 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 26 Jun 2025 11:32:32 -0700 Subject: [PATCH 11/36] Fixed spelling and ran Black --- .../notebooks/docs/tut/core/flash_unit.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_doc.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_exercise.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_solution.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_test.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_usr.ipynb | 2 +- .../notebooks/docs/tut/core/hda_flowsheet.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_doc.ipynb | 11 +++++------ .../docs/tut/core/hda_flowsheet_exercise.ipynb | 11 +++++------ .../docs/tut/core/hda_flowsheet_solution.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_test.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_usr.ipynb | 11 +++++------ 12 files changed, 36 insertions(+), 42 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index a44b3af3..98bea68f 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 07569d68..bb186921 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 81943bc9..7896bd57 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -164,7 +164,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index bf8397d4..9cb8329c 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 723382dd..d0a1de40 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index bf8397d4..9cb8329c 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index ec841572..1657be48 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -1565,7 +1565,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1592,7 +1591,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1642,10 +1641,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 6434a3ca..4e387ef6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1358,7 +1358,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1385,7 +1384,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1435,10 +1434,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 4b548c13..fa69aa58 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1426,7 +1426,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1453,7 +1452,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1503,10 +1502,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 1f252838..a34d330c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1529,7 +1529,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1556,7 +1555,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1606,10 +1605,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index de891a01..4ab76338 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1394,7 +1394,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1421,7 +1420,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1471,10 +1470,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 1f252838..a34d330c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1529,7 +1529,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1556,7 +1555,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1606,10 +1605,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" From 14cdccb6a591f8fd3b8b9a4b39735c8b900618b2 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 26 Jun 2025 13:28:56 -0700 Subject: [PATCH 12/36] Fixing pytesting for earlier versions --- .../docs/tut/core/hda_flowsheet.ipynb | 908 +++++++----------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 828 +++++++--------- .../tut/core/hda_flowsheet_exercise.ipynb | 451 +++++---- .../tut/core/hda_flowsheet_solution.ipynb | 872 +++++++---------- .../docs/tut/core/hda_flowsheet_test.ipynb | 864 +++++++---------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 872 +++++++---------- 6 files changed, 1933 insertions(+), 2862 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 1657be48..58481dd5 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -882,8 +882,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.360025Z", - "start_time": "2025-06-24T19:31:55.338112Z" + "end_time": "2025-06-26T20:17:04.810084Z", + "start_time": "2025-06-26T20:17:04.786754Z" } }, "source": [ @@ -904,8 +904,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -943,8 +943,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -975,8 +975,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -996,8 +996,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1028,8 +1028,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1066,8 +1066,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1083,8 +1083,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1105,8 +1105,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1139,8 +1139,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1156,8 +1156,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1181,8 +1181,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.652507Z", - "start_time": "2025-06-24T19:31:55.628692Z" + "end_time": "2025-06-26T20:17:05.104838Z", + "start_time": "2025-06-26T20:17:05.080097Z" } }, "source": [ @@ -1199,8 +1199,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1240,8 +1240,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1269,8 +1269,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1300,8 +1300,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1340,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1377,8 +1377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1404,8 +1404,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1428,8 +1428,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1451,8 +1451,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1480,8 +1480,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1511,8 +1511,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1525,7 +1525,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1560,8 +1560,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1598,27 +1598,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1635,8 +1635,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1659,9 +1659,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1699,25 +1699,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1747,8 +1747,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1792,8 +1792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1833,8 +1833,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1852,8 +1852,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1873,9 +1873,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1913,298 +1913,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2219,8 +2056,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.324104Z", - "start_time": "2025-06-24T19:31:58.321662Z" + "end_time": "2025-06-26T20:17:07.713878Z", + "start_time": "2025-06-26T20:17:07.711084Z" } }, "source": [ @@ -2255,8 +2092,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2276,8 +2113,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2295,7 +2132,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2321,8 +2158,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2333,7 +2170,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2346,8 +2183,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.533714Z", - "start_time": "2025-06-24T19:31:58.461636Z" + "end_time": "2025-06-26T20:17:08.014719Z", + "start_time": "2025-06-26T20:17:07.926032Z" } }, "source": [ @@ -2369,8 +2206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2411,7 +2248,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2424,8 +2261,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.576962Z", - "start_time": "2025-06-24T19:31:58.573769Z" + "end_time": "2025-06-26T20:17:08.063578Z", + "start_time": "2025-06-26T20:17:08.060157Z" } }, "source": [ @@ -2447,8 +2284,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2467,7 +2304,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2514,8 +2351,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2535,8 +2372,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2572,8 +2409,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2589,8 +2426,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2607,8 +2444,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.762582Z", - "start_time": "2025-06-24T19:31:58.737160Z" + "end_time": "2025-06-26T20:17:08.275146Z", + "start_time": "2025-06-26T20:17:08.249526Z" } }, "source": [ @@ -2636,8 +2473,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2670,8 +2507,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2687,8 +2524,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2710,8 +2547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2736,8 +2573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2772,8 +2609,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2789,8 +2626,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2813,8 +2650,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2837,8 +2674,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2854,9 +2691,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2911,74 +2748,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2991,8 +2809,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.213739Z", - "start_time": "2025-06-24T19:31:59.210358Z" + "end_time": "2025-06-26T20:17:08.683743Z", + "start_time": "2025-06-26T20:17:08.679403Z" } }, "source": [ @@ -3017,8 +2835,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -3041,7 +2859,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -3071,7 +2889,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -3112,8 +2930,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.287634Z", - "start_time": "2025-06-24T19:31:59.283037Z" + "end_time": "2025-06-26T20:17:08.756874Z", + "start_time": "2025-06-26T20:17:08.753678Z" } }, "source": [ @@ -3134,8 +2952,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ @@ -3181,8 +2999,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.345387Z", - "start_time": "2025-06-24T19:31:59.340713Z" + "end_time": "2025-06-26T20:17:08.825473Z", + "start_time": "2025-06-26T20:17:08.820372Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 4e387ef6..219269e0 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -298,8 +298,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -434,8 +434,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -472,8 +472,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -506,8 +506,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -525,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -547,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -572,8 +572,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -595,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -627,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -654,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -683,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -706,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -737,8 +737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -771,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -800,8 +800,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -839,8 +839,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -871,8 +871,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -892,8 +892,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -924,8 +924,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -942,8 +942,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -964,8 +964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -982,8 +982,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1033,8 +1033,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1062,8 +1062,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1093,8 +1093,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1133,8 +1133,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1170,8 +1170,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1197,8 +1197,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1221,8 +1221,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1244,8 +1244,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1273,8 +1273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1318,7 +1318,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1353,8 +1353,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1391,27 +1391,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1428,8 +1428,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1452,9 +1452,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1492,25 +1492,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1540,8 +1540,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1585,8 +1585,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1607,8 +1607,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1628,9 +1628,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1668,298 +1668,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -1994,8 +1831,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2013,7 +1850,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2039,8 +1876,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2051,7 +1888,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2068,8 +1905,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2110,7 +1947,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2127,8 +1964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2147,7 +1984,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2194,8 +2031,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2215,8 +2052,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2235,8 +2072,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2283,8 +2120,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2306,8 +2143,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2332,8 +2169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2352,8 +2189,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2376,8 +2213,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2400,8 +2237,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2417,9 +2254,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2474,74 +2311,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2560,8 +2378,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2584,7 +2402,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2614,7 +2432,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2659,8 +2477,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index fa69aa58..6040564f 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -233,8 +233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -273,8 +273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -297,8 +297,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -319,8 +319,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -345,8 +345,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -396,8 +396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -422,8 +422,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -447,8 +447,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -485,8 +485,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -519,8 +519,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -552,8 +552,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -573,8 +573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -598,8 +598,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -621,8 +621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -653,8 +653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -680,8 +680,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -709,8 +709,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -732,8 +732,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -763,8 +763,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -797,8 +797,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -826,8 +826,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -865,8 +865,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -897,8 +897,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -918,8 +918,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -950,8 +950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -988,8 +988,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1009,8 +1009,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1043,8 +1043,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1060,8 +1060,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1101,8 +1101,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1130,8 +1130,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1161,8 +1161,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1201,8 +1201,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1238,8 +1238,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1265,8 +1265,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1289,8 +1289,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1312,8 +1312,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1372,8 +1372,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1386,7 +1386,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1421,8 +1421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1459,27 +1459,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1496,8 +1496,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1520,9 +1520,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1560,25 +1560,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1608,8 +1608,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1653,8 +1653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1694,8 +1694,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1729,8 +1729,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -1750,8 +1750,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -1769,7 +1769,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -1795,8 +1795,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -1807,7 +1807,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -1824,8 +1824,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -1866,7 +1866,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -1883,8 +1883,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -1903,7 +1903,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -1950,8 +1950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -1971,8 +1971,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2008,8 +2008,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2037,8 +2037,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2071,8 +2071,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2092,8 +2092,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2118,8 +2118,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2154,8 +2154,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2175,8 +2175,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2199,8 +2199,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2216,9 +2216,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2273,74 +2273,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2359,8 +2340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2383,7 +2364,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2413,7 +2394,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2458,8 +2439,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index a34d330c..56db9c65 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -886,8 +886,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -925,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -957,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -978,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1010,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1048,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1065,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1087,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1121,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1138,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1163,8 +1163,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1204,8 +1204,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1264,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1368,8 +1368,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1392,8 +1392,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1415,8 +1415,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1444,8 +1444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1475,8 +1475,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1489,7 +1489,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1524,8 +1524,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1562,27 +1562,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1599,8 +1599,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1623,9 +1623,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1663,25 +1663,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1711,8 +1711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1756,8 +1756,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1797,8 +1797,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1816,8 +1816,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1837,9 +1837,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1877,298 +1877,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2199,8 +2036,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2220,8 +2057,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2239,7 +2076,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2277,7 +2114,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2294,8 +2131,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2336,7 +2173,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2353,8 +2190,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2373,7 +2210,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2420,8 +2257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2441,8 +2278,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2478,8 +2315,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2495,8 +2332,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2525,8 +2362,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2559,8 +2396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2576,8 +2413,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2599,8 +2436,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2625,8 +2462,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2661,8 +2498,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2678,8 +2515,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2702,8 +2539,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2726,8 +2563,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2743,9 +2580,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2800,74 +2637,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2886,8 +2704,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2910,7 +2728,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2940,7 +2758,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2985,8 +2803,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 4ab76338..6369d0f7 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -298,8 +298,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -434,8 +434,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -472,8 +472,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -506,8 +506,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -525,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -547,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -572,8 +572,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -595,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -627,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -654,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -683,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -706,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -737,8 +737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -771,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -796,8 +796,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.360025Z", - "start_time": "2025-06-24T19:31:55.338112Z" + "end_time": "2025-06-26T20:17:04.810084Z", + "start_time": "2025-06-26T20:17:04.786754Z" } }, "source": [ @@ -818,8 +818,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -889,8 +889,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -910,8 +910,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -942,8 +942,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -960,8 +960,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -982,8 +982,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1000,8 +1000,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1025,8 +1025,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.652507Z", - "start_time": "2025-06-24T19:31:55.628692Z" + "end_time": "2025-06-26T20:17:05.104838Z", + "start_time": "2025-06-26T20:17:05.080097Z" } }, "source": [ @@ -1069,8 +1069,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1098,8 +1098,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1129,8 +1129,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1169,8 +1169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1206,8 +1206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1257,8 +1257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1280,8 +1280,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1309,8 +1309,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1340,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1354,7 +1354,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1389,8 +1389,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1427,27 +1427,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1464,8 +1464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1488,9 +1488,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1528,25 +1528,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1576,8 +1576,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1621,8 +1621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1643,8 +1643,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1664,9 +1664,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1704,298 +1704,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2010,8 +1847,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.324104Z", - "start_time": "2025-06-24T19:31:58.321662Z" + "end_time": "2025-06-26T20:17:07.713878Z", + "start_time": "2025-06-26T20:17:07.711084Z" } }, "source": [ @@ -2050,8 +1887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2069,7 +1906,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2095,8 +1932,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2107,7 +1944,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2120,8 +1957,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.533714Z", - "start_time": "2025-06-24T19:31:58.461636Z" + "end_time": "2025-06-26T20:17:08.014719Z", + "start_time": "2025-06-26T20:17:07.926032Z" } }, "source": [ @@ -2143,8 +1980,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2185,7 +2022,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2198,8 +2035,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.576962Z", - "start_time": "2025-06-24T19:31:58.573769Z" + "end_time": "2025-06-26T20:17:08.063578Z", + "start_time": "2025-06-26T20:17:08.060157Z" } }, "source": [ @@ -2221,8 +2058,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2241,7 +2078,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2288,8 +2125,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2309,8 +2146,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2329,8 +2166,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2347,8 +2184,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.762582Z", - "start_time": "2025-06-24T19:31:58.737160Z" + "end_time": "2025-06-26T20:17:08.275146Z", + "start_time": "2025-06-26T20:17:08.249526Z" } }, "source": [ @@ -2376,8 +2213,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2394,8 +2231,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2417,8 +2254,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2443,8 +2280,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2463,8 +2300,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2487,8 +2324,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2511,8 +2348,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2528,9 +2365,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2585,74 +2422,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2665,8 +2483,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.213739Z", - "start_time": "2025-06-24T19:31:59.210358Z" + "end_time": "2025-06-26T20:17:08.683743Z", + "start_time": "2025-06-26T20:17:08.679403Z" } }, "source": [ @@ -2691,8 +2509,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2715,7 +2533,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2745,7 +2563,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2786,8 +2604,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.287634Z", - "start_time": "2025-06-24T19:31:59.283037Z" + "end_time": "2025-06-26T20:17:08.756874Z", + "start_time": "2025-06-26T20:17:08.753678Z" } }, "source": [ @@ -2808,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ @@ -2855,8 +2673,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.345387Z", - "start_time": "2025-06-24T19:31:59.340713Z" + "end_time": "2025-06-26T20:17:08.825473Z", + "start_time": "2025-06-26T20:17:08.820372Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index a34d330c..56db9c65 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -886,8 +886,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -925,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -957,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -978,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1010,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1048,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1065,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1087,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1121,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1138,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1163,8 +1163,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1204,8 +1204,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1264,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1368,8 +1368,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1392,8 +1392,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1415,8 +1415,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1444,8 +1444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1475,8 +1475,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1489,7 +1489,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1524,8 +1524,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1562,27 +1562,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1599,8 +1599,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1623,9 +1623,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1663,25 +1663,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1711,8 +1711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1756,8 +1756,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1797,8 +1797,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1816,8 +1816,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1837,9 +1837,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1877,298 +1877,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2199,8 +2036,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2220,8 +2057,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2239,7 +2076,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2277,7 +2114,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2294,8 +2131,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2336,7 +2173,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2353,8 +2190,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2373,7 +2210,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2420,8 +2257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2441,8 +2278,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2478,8 +2315,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2495,8 +2332,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2525,8 +2362,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2559,8 +2396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2576,8 +2413,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2599,8 +2436,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2625,8 +2462,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2661,8 +2498,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2678,8 +2515,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2702,8 +2539,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2726,8 +2563,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2743,9 +2580,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2800,74 +2637,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2886,8 +2704,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2910,7 +2728,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2940,7 +2758,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2985,8 +2803,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ From 5ced5b0279ae464098fb06fa5936fe8b7948dadc Mon Sep 17 00:00:00 2001 From: Keith Beattie Date: Thu, 21 Aug 2025 11:20:08 -0700 Subject: [PATCH 13/36] Update core.yml empty change to trigger github actions --- .github/workflows/core.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 42610e1f..75fae0cf 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -1,5 +1,4 @@ name: Tests - on: push: branches: @@ -115,4 +114,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: pytest-xdist-logs-${{ matrix.python-version }}-${{ runner.os }} - path: "tests_*.log" \ No newline at end of file + path: "tests_*.log" From f165fa2cb96c8a4209ac7b6c3307777cad0af2f6 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 25 Aug 2025 10:13:29 -0600 Subject: [PATCH 14/36] Created config files to implement modular properties framework and initialized the HDA flowsheet files to work with the modular properties framework. Currently not working due to unit model initialization error. --- .../mod/hda/hda_ideal_VLE_modular.py | 252 +++ .../mod/hda/hda_reaction_modular.py | 91 + .../docs/tut/core/hda_flowsheet.ipynb | 1459 +++-------------- .../notebooks/docs/tut/core/hda_flowsheet.py | 553 +++++++ 4 files changed, 1160 insertions(+), 1195 deletions(-) create mode 100644 idaes_examples/mod/hda/hda_ideal_VLE_modular.py create mode 100644 idaes_examples/mod/hda/hda_reaction_modular.py create mode 100644 idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py diff --git a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py new file mode 100644 index 00000000..7aaf9f76 --- /dev/null +++ b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py @@ -0,0 +1,252 @@ +################################################################################# +# The Institute for the Design of Advanced Energy Systems Integrated Platform +# Framework (IDAES IP) was produced under the DOE Institute for the +# Design of Advanced Energy Systems (IDAES). +# +# Copyright (c) 2018-2024 by the software owners: The Regents of the +# University of California, through Lawrence Berkeley National Laboratory, +# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon +# University, West Virginia University Research Corporation, et al. +# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md +# for full copyright and license information. +################################################################################# +""" +Benzene-Toluene phase equilibrium package using ideal liquid and vapor. + +Example property package using the Generic Property Package Framework. +This exmample shows how to set up a property package to do benzene-toluene +phase equilibrium in the generic framework using ideal liquid and vapor +assumptions along with methods drawn from the pre-built IDAES property +libraries. +""" +# Import Pyomo units +from pyomo.environ import units as pyunits + +# Import IDAES cores +from idaes.core import LiquidPhase, VaporPhase, Component +import idaes.logger as idaeslog + +from idaes.models.properties.modular_properties.state_definitions import FpcTP +from idaes.models.properties.modular_properties.eos.ideal import Ideal +from idaes.models.properties.modular_properties.phase_equil import SmoothVLE +from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( + IdealBubbleDew, +) +from idaes.models.properties.modular_properties.phase_equil.forms import fugacity +from idaes.models.properties.modular_properties.pure import Perrys +from idaes.models.properties.modular_properties.pure import RPP5 + +# Set up logger +_log = idaeslog.getLogger(__name__) + +# --------------------------------------------------------------------- +# Configuration dictionary for an ideal Benzene-Toluene system + +# Data Sources: +# [1] The Properties of Gases and Liquids (1987) +# 4th edition, Chemical Engineering Series - Robert C. Reid +# [2] Perry's Chemical Engineers' Handbook 7th Ed. +# [3] Engineering Toolbox, https://www.engineeringtoolbox.com +# Retrieved 1st December, 2019 + +thermo_config = { + # Specifying components + "components": { + "benzene": { + "type": Component, + "elemental_composition": {"C": 6, "H": 6}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (78.1136e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (48.9e5, pyunits.Pa), # [1] + "temperature_crit": (562.2, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (1.0162, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.2655, None), + "3": (562.16, pyunits.K), + "4": (0.28212, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (-3.392e1, None), # [1] + "a1": (4.739e-1, pyunits.K**-1), + "a2": (-3.017e-4, pyunits.K**-2), + "a3": (7.130e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (1.29e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.7e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (6.48e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (49.0e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (82.9e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (4.202, pyunits.dimensionless), # [1] + "B": (1322, pyunits.K), + "C": (-38.56, pyunits.K), + }, + }, + }, + "toluene": { + "type": Component, + "elemental_composition": {"C": 7, "H": 8}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (92.1405e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (41e5, pyunits.Pa), # [1] + "temperature_crit": (591.8, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (0.8488, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.26655, None), + "3": (591.8, pyunits.K), + "4": (0.2878, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (-2.435e1, None), # [1] + "a1": (5.125e-1, pyunits.K**-1), + "a2": (-2.765e-4, pyunits.K**-2), + "a3": (4.911e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (1.40e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.52e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (6.95e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (12.0e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (50.1e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (4.216, pyunits.dimensionless), # [1] + "B": (1435, pyunits.K), + "C": (-43.33, pyunits.K), + }, + }, + }, + "hydrogen": { + "type": Component, + "elemental_composition": {"H": 2}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (2.016e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (12.9e5, pyunits.Pa), # [1] + "temperature_crit": (33.0, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (5.414, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.34893, None), + "3": (33.19, pyunits.K), + "4": (0.2706, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (2.714e1, None), # [1] + "a1": (9.274e-3, pyunits.K**-1), + "a2": (-1.381e-5, pyunits.K**-2), + "a3": (7.645e-9, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (3.543, pyunits.dimensionless), # [1] + "B": (99.40, pyunits.K), + "C": (7.726, pyunits.K), + }, + }, + }, + "methane": { + "type": Component, + "elemental_composition": {"C": 1, "H": 4}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (16.043e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (4.599e6, pyunits.Pa), # [1] + "temperature_crit": (190.564, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (2.9214, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.28976, None), + "3": (190.56, pyunits.K), + "4": (0.28881, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (1.925e1, None), # [1] + "a1": (5.213e-2, pyunits.K**-1), + "a2": (1.197e-5, pyunits.K**-2), + "a3": (-1.132e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K**-4), + }, + "cp_mol_liq_comp_coeff": { + "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (3.990, pyunits.dimensionless), # [1] + "B": (443.0, pyunits.K), + "C": (-0.49, pyunits.K), + }, + }, + }, + + }, + # Specifying phases + "phases": { + "Liq": {"type": LiquidPhase, "equation_of_state": Ideal}, + "Vap": {"type": VaporPhase, "equation_of_state": Ideal}, + }, + # + # # Set base units of measurement + "base_units": { + "time": pyunits.s, + "length": pyunits.m, + "mass": pyunits.kg, + "amount": pyunits.mol, + "temperature": pyunits.K, + }, + # # Specifying state definition + "state_definition": FpcTP, + "state_bounds": { + "flow_mol_phase_comp": (1e-12, .5, 100, pyunits.mol / pyunits.s), + "temperature": (298, 298.15, 1000, pyunits.K), + "pressure": (100000, 101325, 1000000, pyunits.Pa), + }, + "pressure_ref": (101325, pyunits.Pa), + "temperature_ref": (298.15, pyunits.K), + # Defining phase equilibria + "phases_in_equilibrium": [("Vap", "Liq")], + "phase_equilibrium_state": {("Vap", "Liq"): SmoothVLE}, + "bubble_dew_method": IdealBubbleDew, +} diff --git a/idaes_examples/mod/hda/hda_reaction_modular.py b/idaes_examples/mod/hda/hda_reaction_modular.py new file mode 100644 index 00000000..831c8684 --- /dev/null +++ b/idaes_examples/mod/hda/hda_reaction_modular.py @@ -0,0 +1,91 @@ +################################################################################# +# The Institute for the Design of Advanced Energy Systems Integrated Platform +# Framework (IDAES IP) was produced under the DOE Institute for the +# Design of Advanced Energy Systems (IDAES). +# +# Copyright (c) 2018-2024 by the software owners: The Regents of the +# University of California, through Lawrence Berkeley National Laboratory, +# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon +# University, West Virginia University Research Corporation, et al. +# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md +# for full copyright and license information. +################################################################################# +""" +Benzene-Toluene phase equilibrium package using ideal liquid and vapor. + +Example property package using the Generic Property Package Framework. +This exmample shows how to set up a property package to do benzene-toluene +phase equilibrium in the generic framework using ideal liquid and vapor +assumptions along with methods drawn from the pre-built IDAES property +libraries. +""" +# Import Pyomo units +from pyomo.environ import units as pyunits + +# Import IDAES cores +from idaes.core import LiquidPhase, VaporPhase, Component +import idaes.logger as idaeslog + +from idaes.models.properties.modular_properties.state_definitions import FTPx +from idaes.models.properties.modular_properties.eos.ideal import Ideal +from idaes.models.properties.modular_properties.phase_equil import SmoothVLE +from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( + IdealBubbleDew, +) +from idaes.models.properties.modular_properties.phase_equil.forms import fugacity +from idaes.models.properties.modular_properties.pure import Perrys +from idaes.models.properties.modular_properties.pure import RPP5 +from idaes.models.properties.modular_properties.reactions.rate_forms import power_law_rate +from idaes.models.properties.modular_properties.reactions.dh_rxn import constant_dh_rxn +from idaes.models.properties.modular_properties.reactions.rate_constant import arrhenius +from idaes.models.properties.modular_properties.base.utility import ConcentrationForm + +# Set up logger +_log = idaeslog.getLogger(__name__) + +# --------------------------------------------------------------------- +# Configuration dictionary for an ideal Benzene-Toluene system + +# Data Sources: +# [1] The Properties of Gases and Liquids (1987) +# 4th edition, Chemical Engineering Series - Robert C. Reid +# [2] Perry's Chemical Engineers' Handbook 7th Ed. +# [3] Engineering Toolbox, https://www.engineeringtoolbox.com +# Retrieved 1st December, 2019 + +reaction_config = { + + 'rate_reactions': { + "hydrodealkylation": { + "stoichiometry": { + ("Vap", "benzene"): 1, + ("Vap", "toluene"): -1, + ("Vap", "hydrogen"): -1, + ("Vap", "methane"): 1, + }, + "heat_of_reaction": constant_dh_rxn, + "rate_constant": arrhenius, + "rate_form": power_law_rate, + "concentration_form": ConcentrationForm.partialPressure, + "parameter_data": { + "dh_rxn_ref": (-1.08e5, pyunits.J / pyunits.mol), + "arrhenius_const": (6.3e10, pyunits.mol * pyunits.m ** -3 * pyunits.s ** -1 * pyunits.Pa ** -1.5), + "energy_activation": (217.6e3, pyunits.J / pyunits.mol), + "reaction_order": { + ("Vap", "benzene"): 0, + ("Vap", "toluene"): 1.0, + ("Vap", "hydrogen"): .5, + ("Vap", "methane"): 0, } + } + } + }, + + # Set base units of measurement + "base_units": { + "time": pyunits.s, + "length": pyunits.m, + "mass": pyunits.kg, + "amount": pyunits.mol, + "temperature": pyunits.K, + }, +} diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 58481dd5..a9654d09 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" + "end_time": "2025-07-15T22:29:16.862036Z", + "start_time": "2025-07-15T22:29:16.858494Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" + "end_time": "2025-07-15T22:29:17.440971Z", + "start_time": "2025-07-15T22:29:17.070381Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" + "end_time": "2025-07-15T22:29:18.862462Z", + "start_time": "2025-07-15T22:29:17.454785Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" + "end_time": "2025-07-15T22:29:18.975963Z", + "start_time": "2025-07-15T22:29:18.870712Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" + "end_time": "2025-07-15T22:29:18.986206Z", + "start_time": "2025-07-15T22:29:18.983178Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" + "end_time": "2025-07-15T22:29:19.000804Z", + "start_time": "2025-07-15T22:29:18.997523Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" + "end_time": "2025-07-15T22:29:19.013373Z", + "start_time": "2025-07-15T22:29:19.010633Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" + "end_time": "2025-07-15T22:29:19.029237Z", + "start_time": "2025-07-15T22:29:19.021824Z" } }, "source": [ @@ -302,6 +302,27 @@ "outputs": [], "execution_count": 8 }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-15T22:29:19.117688Z", + "start_time": "2025-07-15T22:29:19.037801Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 9 + }, { "cell_type": "markdown", "metadata": {}, @@ -315,8 +336,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" + "end_time": "2025-07-15T22:29:19.131934Z", + "start_time": "2025-07-15T22:29:19.127335Z" } }, "source": [ @@ -324,7 +345,7 @@ "m.fs = FlowsheetBlock(dynamic=False)" ], "outputs": [], - "execution_count": 9 + "execution_count": 10 }, { "cell_type": "markdown", @@ -337,18 +358,68 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" + "end_time": "2025-07-15T22:29:20.186702Z", + "start_time": "2025-07-15T22:29:19.143102Z" } }, "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" + "# m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + "# property_package=m.fs.thermo_params\n", + "# )\n", + "\n", + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)" ], - "outputs": [], - "execution_count": 10 + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2025-07-15 16:29:19 [ERROR] idaes.core.base.process_block: Failure in build: fs.thermo_params\n", + "Traceback (most recent call last):\n", + " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py\", line 41, in _rule_default\n", + " b.build()\n", + " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py\", line 470, in build\n", + " for p in self.phase_list:\n", + " ^^^^^^^^^^^^^^^\n", + " File \"C:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py\", line 550, in __getattr__\n", + " raise AttributeError(\n", + "AttributeError: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'\n", + "ERROR: Constructing component 'fs.thermo_params' from data=None failed:\n", + " AttributeError: '_ScalarGenericParameterBlock' object has no attribute\n", + " 'phase_list'\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'_ScalarGenericParameterBlock' object has no attribute 'phase_list'", + "output_type": "error", + "traceback": [ + "\u001B[31m---------------------------------------------------------------------------\u001B[39m", + "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)", + "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[11]\u001B[39m\u001B[32m, line 6\u001B[39m\n\u001B[32m 1\u001B[39m \u001B[38;5;66;03m# m.fs.thermo_params = thermo_props.HDAParameterBlock()\u001B[39;00m\n\u001B[32m 2\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\u001B[39;00m\n\u001B[32m 3\u001B[39m \u001B[38;5;66;03m# property_package=m.fs.thermo_params\u001B[39;00m\n\u001B[32m 4\u001B[39m \u001B[38;5;66;03m# )\u001B[39;00m\n\u001B[32m----> \u001B[39m\u001B[32m6\u001B[39m \u001B[43mm\u001B[49m\u001B[43m.\u001B[49m\u001B[43mfs\u001B[49m\u001B[43m.\u001B[49m\u001B[43mthermo_params\u001B[49m = GenericParameterBlock(**thermo_config)\n\u001B[32m 7\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)\u001B[39;00m\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:571\u001B[39m, in \u001B[36mBlockData.__setattr__\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 566\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m name \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m.\u001B[34m__dict__\u001B[39m:\n\u001B[32m 567\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(val, Component):\n\u001B[32m 568\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 569\u001B[39m \u001B[38;5;66;03m# Pyomo components are added with the add_component method.\u001B[39;00m\n\u001B[32m 570\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m571\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43madd_component\u001B[49m\u001B[43m(\u001B[49m\u001B[43mname\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mval\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 572\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 573\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 574\u001B[39m \u001B[38;5;66;03m# Other Python objects are added with the standard __setattr__\u001B[39;00m\n\u001B[32m 575\u001B[39m \u001B[38;5;66;03m# method.\u001B[39;00m\n\u001B[32m 576\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 577\u001B[39m \u001B[38;5;28msuper\u001B[39m(BlockData, \u001B[38;5;28mself\u001B[39m).\u001B[34m__setattr__\u001B[39m(name, val)\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:1101\u001B[39m, in \u001B[36mBlockData.add_component\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 1093\u001B[39m logger.debug(\n\u001B[32m 1094\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mConstructing \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m on \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m from data=\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m\"\u001B[39m,\n\u001B[32m 1095\u001B[39m val.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m,\n\u001B[32m (...)\u001B[39m\u001B[32m 1098\u001B[39m \u001B[38;5;28mstr\u001B[39m(data),\n\u001B[32m 1099\u001B[39m )\n\u001B[32m 1100\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1101\u001B[39m \u001B[43mval\u001B[49m\u001B[43m.\u001B[49m\u001B[43mconstruct\u001B[49m\u001B[43m(\u001B[49m\u001B[43mdata\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1102\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m:\n\u001B[32m 1103\u001B[39m err = sys.exc_info()[\u001B[32m1\u001B[39m]\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2233\u001B[39m, in \u001B[36mBlock.construct\u001B[39m\u001B[34m(self, data)\u001B[39m\n\u001B[32m 2231\u001B[39m obj.construct(data.get(name, \u001B[38;5;28;01mNone\u001B[39;00m))\n\u001B[32m 2232\u001B[39m \u001B[38;5;66;03m# Trigger the (normal) initialization of the block\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m2233\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_getitem_when_not_present\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_idx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2234\u001B[39m \u001B[38;5;28;01mfinally\u001B[39;00m:\n\u001B[32m 2235\u001B[39m \u001B[38;5;66;03m# We must allow that id(self) may no longer be in\u001B[39;00m\n\u001B[32m 2236\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data, as _getitem_when_not_present will\u001B[39;00m\n\u001B[32m 2237\u001B[39m \u001B[38;5;66;03m# have already removed the entry for scalar blocks (as the\u001B[39;00m\n\u001B[32m 2238\u001B[39m \u001B[38;5;66;03m# BlockData and the Block component are the same object)\u001B[39;00m\n\u001B[32m 2239\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m data \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2148\u001B[39m, in \u001B[36mBlock._getitem_when_not_present\u001B[39m\u001B[34m(self, idx)\u001B[39m\n\u001B[32m 2145\u001B[39m data = \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[32m 2147\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m2148\u001B[39m obj = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_rule\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_block\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2149\u001B[39m \u001B[38;5;66;03m# If the user returns a block, transfer over everything\u001B[39;00m\n\u001B[32m 2150\u001B[39m \u001B[38;5;66;03m# they defined into the empty one we created. We do\u001B[39;00m\n\u001B[32m 2151\u001B[39m \u001B[38;5;66;03m# this inside the try block so that any abstract\u001B[39;00m\n\u001B[32m 2152\u001B[39m \u001B[38;5;66;03m# components declared by the rule have the opportunity\u001B[39;00m\n\u001B[32m 2153\u001B[39m \u001B[38;5;66;03m# to be initialized with data from\u001B[39;00m\n\u001B[32m 2154\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data as they are transferred over.\u001B[39;00m\n\u001B[32m 2155\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m obj \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m _block \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(obj, BlockData):\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\initializer.py:351\u001B[39m, in \u001B[36mIndexedCallInitializer.__call__\u001B[39m\u001B[34m(self, parent, idx)\u001B[39m\n\u001B[32m 349\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m._fcn(parent, *idx)\n\u001B[32m 350\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m--> \u001B[39m\u001B[32m351\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_fcn\u001B[49m\u001B[43m(\u001B[49m\u001B[43mparent\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n", + "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py:41\u001B[39m, in \u001B[36m_rule_default\u001B[39m\u001B[34m(b, *args)\u001B[39m\n\u001B[32m 35\u001B[39m \u001B[38;5;250m\u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 36\u001B[39m \u001B[33;03mDefault rule for ProcessBlock, which calls build(). A different rule can\u001B[39;00m\n\u001B[32m 37\u001B[39m \u001B[33;03mbe specified to add additional build steps, or to not call build at all\u001B[39;00m\n\u001B[32m 38\u001B[39m \u001B[33;03musing the normal rule argument to ProcessBlock init.\u001B[39;00m\n\u001B[32m 39\u001B[39m \u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 40\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m---> \u001B[39m\u001B[32m41\u001B[39m \u001B[43mb\u001B[49m\u001B[43m.\u001B[49m\u001B[43mbuild\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 42\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m:\n\u001B[32m 43\u001B[39m logging.getLogger(\u001B[34m__name__\u001B[39m).exception(\u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33mFailure in build: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mb\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m\"\u001B[39m)\n", + "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py:470\u001B[39m, in \u001B[36mGenericParameterData.build\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 468\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m._electrolyte:\n\u001B[32m 469\u001B[39m pc_set = []\n\u001B[32m--> \u001B[39m\u001B[32m470\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mphase_list\u001B[49m:\n\u001B[32m 471\u001B[39m pobj = \u001B[38;5;28mself\u001B[39m.get_phase(p)\n\u001B[32m 472\u001B[39m pc_list = \u001B[38;5;28mself\u001B[39m.get_phase(p).config.component_list\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:550\u001B[39m, in \u001B[36mBlockData.__getattr__\u001B[39m\u001B[34m(self, val)\u001B[39m\n\u001B[32m 547\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m _component_decorator(\u001B[38;5;28mself\u001B[39m, ModelComponentFactory.get_class(val))\n\u001B[32m 548\u001B[39m \u001B[38;5;66;03m# Since the base classes don't support getattr, we can just\u001B[39;00m\n\u001B[32m 549\u001B[39m \u001B[38;5;66;03m# throw the \"normal\" AttributeError\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m550\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mAttributeError\u001B[39;00m(\n\u001B[32m 551\u001B[39m \u001B[33m\"\u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m object has no attribute \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m\"\u001B[39m % (\u001B[38;5;28mself\u001B[39m.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m, val)\n\u001B[32m 552\u001B[39m )\n", + "\u001B[31mAttributeError\u001B[39m: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'" + ] + } + ], + "execution_count": 11 }, { "cell_type": "markdown", @@ -361,12 +432,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, + "metadata": {}, "source": [ "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", @@ -384,7 +450,7 @@ ")" ], "outputs": [], - "execution_count": 11 + "execution_count": null }, { "cell_type": "markdown", @@ -412,28 +478,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } + ] }, "source": [ "# Todo: Add reactor with the specifications above" ], "outputs": [], - "execution_count": 12 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } + ] }, "source": [ "# Todo: Add reactor with the specifications above\n", @@ -446,7 +504,7 @@ ")" ], "outputs": [], - "execution_count": 13 + "execution_count": null }, { "cell_type": "markdown", @@ -462,12 +520,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", @@ -476,7 +529,7 @@ ")" ], "outputs": [], - "execution_count": 14 + "execution_count": null }, { "cell_type": "markdown", @@ -487,12 +540,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, + "metadata": {}, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -514,7 +562,7 @@ ")" ], "outputs": [], - "execution_count": 15 + "execution_count": null }, { "cell_type": "markdown", @@ -525,12 +573,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, + "metadata": {}, "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -539,7 +582,7 @@ "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], - "execution_count": 16 + "execution_count": null }, { "cell_type": "markdown", @@ -559,19 +602,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, + "metadata": {}, "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" ], "outputs": [], - "execution_count": 17 + "execution_count": null }, { "cell_type": "markdown", @@ -592,35 +630,27 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } + ] }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet" ], "outputs": [], - "execution_count": 18 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } + ] }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" ], "outputs": [], - "execution_count": 19 + "execution_count": null }, { "cell_type": "markdown", @@ -631,12 +661,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, + "metadata": {}, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", @@ -645,7 +670,7 @@ "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], - "execution_count": 20 + "execution_count": null }, { "cell_type": "markdown", @@ -656,19 +681,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, + "metadata": {}, "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" ], "outputs": [], - "execution_count": 21 + "execution_count": null }, { "cell_type": "markdown", @@ -679,17 +699,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, + "metadata": {}, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" ], "outputs": [], - "execution_count": 22 + "execution_count": null }, { "cell_type": "markdown", @@ -711,12 +726,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, + "metadata": {}, "source": [ "m.fs.purity = Expression(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -727,7 +737,7 @@ ")" ], "outputs": [], - "execution_count": 23 + "execution_count": null }, { "cell_type": "markdown", @@ -738,19 +748,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, + "metadata": {}, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" ], "outputs": [], - "execution_count": 24 + "execution_count": null }, { "cell_type": "markdown", @@ -767,19 +772,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, + "metadata": {}, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" ], "outputs": [], - "execution_count": 25 + "execution_count": null }, { "cell_type": "markdown", @@ -790,19 +790,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, + "metadata": {}, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" ], "outputs": [], - "execution_count": 26 + "execution_count": null }, { "cell_type": "markdown", @@ -821,27 +816,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, + "metadata": {}, "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -855,43 +836,26 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, + "metadata": {}, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.810084Z", - "start_time": "2025-06-26T20:17:04.786754Z" - } + ] }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" ], "outputs": [], - "execution_count": 29 + "execution_count": null }, { "cell_type": "markdown", @@ -902,12 +866,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, + "metadata": {}, "source": [ "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", @@ -921,7 +880,7 @@ "m.fs.I101.pressure.fix(350000)" ], "outputs": [], - "execution_count": 30 + "execution_count": null }, { "cell_type": "markdown", @@ -941,12 +900,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, + "metadata": {}, "source": [ "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", @@ -960,7 +914,7 @@ "m.fs.I102.pressure.fix(350000)" ], "outputs": [], - "execution_count": 31 + "execution_count": null }, { "cell_type": "markdown", @@ -973,17 +927,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature.fix(600)" ], "outputs": [], - "execution_count": 32 + "execution_count": null }, { "cell_type": "markdown", @@ -994,12 +943,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, + "metadata": {}, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", @@ -1015,7 +959,7 @@ "m.fs.R101.heat_duty.fix(0)" ], "outputs": [], - "execution_count": 33 + "execution_count": null }, { "cell_type": "markdown", @@ -1026,18 +970,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" ], "outputs": [], - "execution_count": 34 + "execution_count": null }, { "cell_type": "markdown", @@ -1064,35 +1003,27 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } + ] }, "source": [ "# Todo: Set conditions for Flash F102" ], "outputs": [], - "execution_count": 35 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } + ] }, "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" ], "outputs": [], - "execution_count": 36 + "execution_count": null }, { "cell_type": "markdown", @@ -1103,18 +1034,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, + "metadata": {}, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" ], "outputs": [], - "execution_count": 37 + "execution_count": null }, { "cell_type": "markdown", @@ -1137,71 +1063,47 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } + ] }, "source": [ "# Todo: print the degrees of freedom" ], "outputs": [], - "execution_count": 38 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } + ] }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.104838Z", - "start_time": "2025-06-26T20:17:05.080097Z" - } + ] }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ], "outputs": [], - "execution_count": 40 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } + ] }, "source": [], "outputs": [], @@ -1238,12 +1140,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, + "metadata": {}, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -1256,7 +1153,7 @@ "order = seq.calculation_order(G)" ], "outputs": [], - "execution_count": 41 + "execution_count": null }, { "cell_type": "markdown", @@ -1267,26 +1164,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, + "metadata": {}, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1298,31 +1182,14 @@ { "cell_type": "code", "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } + "scrolled": true }, "source": [ "for o in order:\n", " print(o[0].name)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1338,12 +1205,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, + "metadata": {}, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1364,7 +1226,7 @@ "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" ], "outputs": [], - "execution_count": 44 + "execution_count": null }, { "cell_type": "markdown", @@ -1375,12 +1237,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, + "metadata": {}, "source": [ "def function(unit):\n", " try:\n", @@ -1391,7 +1248,7 @@ " solver.solve(unit)" ], "outputs": [], - "execution_count": 45 + "execution_count": null }, { "cell_type": "markdown", @@ -1402,17 +1259,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, + "metadata": {}, "source": [ "# seq.run(m, function)" ], "outputs": [], - "execution_count": 46 + "execution_count": null }, { "cell_type": "markdown", @@ -1426,17 +1278,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, + "metadata": {}, "source": [ "from idaes.core.util.initialization import propagate_state" ], "outputs": [], - "execution_count": 47 + "execution_count": null }, { "cell_type": "markdown", @@ -1449,25 +1296,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, + "metadata": {}, "source": [ "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1478,27 +1312,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, + "metadata": {}, "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1509,12 +1330,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, + "metadata": {}, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1538,16 +1354,8 @@ "DOF_initial = degrees_of_freedom(m)\n", "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1558,12 +1366,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", @@ -1593,36 +1396,8 @@ ") # Establish connection between Second Flash Unit and Toluene Product\n", "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1633,12 +1408,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, + "metadata": {}, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1649,92 +1419,8 @@ "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1745,12 +1431,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, + "metadata": {}, "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1761,16 +1442,8 @@ " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", ")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1790,12 +1463,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, + "metadata": {}, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1805,7 +1473,7 @@ "}" ], "outputs": [], - "execution_count": 54 + "execution_count": null }, { "cell_type": "markdown", @@ -1831,11 +1499,7 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } + ] }, "source": [ "# Create the solver object\n", @@ -1843,18 +1507,14 @@ "# Solve the model" ], "outputs": [], - "execution_count": 55 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } + ] }, "source": [ "# Create the solver object\n", @@ -1863,202 +1523,15 @@ "# Solve the model\n", "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.713878Z", - "start_time": "2025-06-26T20:17:07.711084Z" - } + ] }, "source": [ "# Check solver solve status\n", @@ -2067,7 +1540,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 57 + "execution_count": null }, { "cell_type": "markdown", @@ -2090,17 +1563,13 @@ "metadata": { "tags": [ "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } + ] }, "source": [ "# m.fs.visualize(\"HDA-Flowsheet\")" ], "outputs": [], - "execution_count": 58 + "execution_count": null }, { "cell_type": "markdown", @@ -2111,41 +1580,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, + "metadata": {}, "source": [ "m.fs.report()" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -2156,36 +1596,19 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, + "metadata": {}, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.014719Z", - "start_time": "2025-06-26T20:17:07.926032Z" - } + ] }, "source": [ "import pytest\n", @@ -2193,7 +1616,7 @@ "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" ], "outputs": [], - "execution_count": 61 + "execution_count": null }, { "cell_type": "markdown", @@ -2204,66 +1627,22 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, + "metadata": {}, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.063578Z", - "start_time": "2025-06-26T20:17:08.060157Z" - } + ] }, "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", @@ -2271,7 +1650,7 @@ "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" ], "outputs": [], - "execution_count": 63 + "execution_count": null }, { "cell_type": "markdown", @@ -2282,12 +1661,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, + "metadata": {}, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -2297,26 +1671,8 @@ "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -2349,17 +1705,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, + "metadata": {}, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" ], "outputs": [], - "execution_count": 65 + "execution_count": null }, { "cell_type": "markdown", @@ -2370,12 +1721,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", @@ -2383,7 +1729,7 @@ "m.fs.F102.vap_outlet.temperature.unfix()" ], "outputs": [], - "execution_count": 66 + "execution_count": null }, { "cell_type": "markdown", @@ -2407,52 +1753,40 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } + ] }, "source": [ "# Todo: Unfix deltaP for F102" ], "outputs": [], - "execution_count": 67 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } + ] }, "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" ], "outputs": [], - "execution_count": 68 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.275146Z", - "start_time": "2025-06-26T20:17:08.249526Z" - } + ] }, "source": [ "assert degrees_of_freedom(m) == 5" ], "outputs": [], - "execution_count": 69 + "execution_count": null }, { "cell_type": "markdown", @@ -2471,18 +1805,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" ], "outputs": [], - "execution_count": 70 + "execution_count": null }, { "cell_type": "markdown", @@ -2505,28 +1834,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } + ] }, "source": [ "# Todo: Set the bounds for reactor outlet temperature" ], "outputs": [], - "execution_count": 71 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } + ] }, "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", @@ -2534,7 +1855,7 @@ "m.fs.R101.outlet.temperature[0].setub(800)" ], "outputs": [], - "execution_count": 72 + "execution_count": null }, { "cell_type": "markdown", @@ -2545,12 +1866,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -2560,7 +1876,7 @@ "m.fs.F102.vap_outlet.pressure[0].setub(110000)" ], "outputs": [], - "execution_count": 73 + "execution_count": null }, { "cell_type": "markdown", @@ -2571,12 +1887,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, + "metadata": {}, "source": [ "m.fs.overhead_loss = Constraint(\n", " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -2584,7 +1895,7 @@ ")" ], "outputs": [], - "execution_count": 74 + "execution_count": null }, { "cell_type": "markdown", @@ -2607,28 +1918,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } + ] }, "source": [ "# Todo: Add minimum product flow constraint" ], "outputs": [], - "execution_count": 75 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } + ] }, "source": [ "# Todo: Add minimum product flow constraint\n", @@ -2637,7 +1940,7 @@ ")" ], "outputs": [], - "execution_count": 76 + "execution_count": null }, { "cell_type": "markdown", @@ -2648,17 +1951,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, + "metadata": {}, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" ], "outputs": [], - "execution_count": 77 + "execution_count": null }, { "cell_type": "markdown", @@ -2672,146 +1970,19 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, + "metadata": {}, "source": [ "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.683743Z", - "start_time": "2025-06-26T20:17:08.679403Z" - } + ] }, "source": [ "# Check for solver solve status\n", @@ -2820,7 +1991,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 79 + "execution_count": null }, { "cell_type": "markdown", @@ -2833,12 +2004,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, + "metadata": {}, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -2854,92 +2020,22 @@ "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.756874Z", - "start_time": "2025-06-26T20:17:08.753678Z" - } + ] }, "source": [ "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" ], "outputs": [], - "execution_count": 81 + "execution_count": null }, { "cell_type": "markdown", @@ -2950,12 +2046,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, + "metadata": {}, "source": [ "print(\n", " f\"\"\"Optimal Values:\n", @@ -2971,37 +2062,15 @@ "\"\"\"\n", ")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.825473Z", - "start_time": "2025-06-26T20:17:08.820372Z" - } + ] }, "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", @@ -3011,7 +2080,7 @@ "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" ], "outputs": [], - "execution_count": 83 + "execution_count": null } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py new file mode 100644 index 00000000..39b56e2f --- /dev/null +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py @@ -0,0 +1,553 @@ + +from pyomo.environ import ( + Constraint, + Var, + ConcreteModel, + Expression, + Objective, + SolverFactory, + TransformationFactory, + value, +) +from pyomo.network import Arc, SequentialDecomposition + +from idaes.core import FlowsheetBlock + +from idaes.models.unit_models import ( + PressureChanger, + IsentropicPressureChangerInitializer, + Mixer, + MixerInitializer, + Separator as Splitter, + SeparatorInitializer, + Heater, + StoichiometricReactor, + Feed, + Product, +) + +# Todo: import flash model from idaes.models.unit_models + +# Todo: import flash model from idaes.models.unit_models +from idaes.models.unit_models import Flash + + +from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption +from idaes.core.util.model_statistics import degrees_of_freedom +from idaes.core.scaling.util import set_scaling_factor +from idaes.core.scaling.autoscaling import AutoScaler + + +import idaes.logger as idaeslog +from idaes.core.solvers import get_solver +from idaes.core.util.exceptions import InitializationError + +from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props +from idaes_examples.mod.hda import hda_reaction as reaction_props + +from idaes.models.properties.modular_properties.base.generic_property import ( + GenericParameterBlock, +) +from idaes.models.properties.modular_properties.base.generic_reaction import ( + GenericReactionParameterBlock, +) +from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config +from idaes_examples.mod.hda.hda_reaction_modular import reaction_config + + +m = ConcreteModel() +m.fs = FlowsheetBlock(dynamic=False) + +thermo_params_og = thermo_props.HDAParameterBlock() +reaction_params_og = reaction_props.HDAReactionParameterBlock(property_package=thermo_params_og) +thermo_params_new = GenericParameterBlock(**thermo_config) +reaction_params_new = GenericReactionParameterBlock(property_package=thermo_params_new, **reaction_config) + +# m.fs.thermo_params = thermo_params_og +# m.fs.reaction_params = reaction_params_og +m.fs.thermo_params = thermo_params_new +m.fs.reaction_params = reaction_params_new + +m.fs.I101 = Feed(property_package=m.fs.thermo_params) + +m.fs.I102 = Feed(property_package=m.fs.thermo_params) + +m.fs.M101 = Mixer( + property_package=m.fs.thermo_params, + num_inlets=3, +) + +m.fs.H101 = Heater( + property_package=m.fs.thermo_params, + has_pressure_change=False, + has_phase_equilibrium=True, +) + +m.fs.R101 = StoichiometricReactor( + property_package=m.fs.thermo_params, + reaction_package=m.fs.reaction_params, + has_heat_of_reaction=True, + has_heat_transfer=True, + has_pressure_change=False, +) + +m.fs.F101 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, +) + +m.fs.S101 = Splitter( + property_package=m.fs.thermo_params, + ideal_separation=False, + outlet_list=["purge", "recycle"], +) + + +m.fs.C101 = PressureChanger( + property_package=m.fs.thermo_params, + compressor=True, + thermodynamic_assumption=ThermodynamicAssumption.isothermal, +) + +m.fs.F102 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, +) + +m.fs.P101 = Product(property_package=m.fs.thermo_params) +m.fs.P102 = Product(property_package=m.fs.thermo_params) +m.fs.P103 = Product(property_package=m.fs.thermo_params) + +m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1) +m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2) +m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet) +m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet) +m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet) +m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet) +m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet) +m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet) +m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3) +m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet) +m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet) +m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet) + +TransformationFactory("network.expand_arcs").apply_to(m) + +m.fs.purity = Expression( + expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + / ( + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "toluene"] + ) +) + +m.fs.cooling_cost = Expression( + expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0]) +) + +m.fs.heating_cost = Expression( + expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0] +) + +m.fs.operating_cost = Expression( + expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) +) + +# autoscaler = AutoScaler() +# autoscaler.scale_model(m) + +print(degrees_of_freedom(m)) + +assert degrees_of_freedom(m) == 29 + +m.fs.I101.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "methane"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "toluene"].fix(0.30) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I101.temperature.fix(303.2) +m.fs.I101.pressure.fix(350000) + +m.fs.I102.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(0.30) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "methane"].fix(0.02) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "toluene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I102.temperature.fix(303.2) +m.fs.I102.pressure.fix(350000) + +m.fs.H101.outlet.temperature.fix(600) + +m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) + +m.fs.R101.conv_constraint = Constraint( + expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] + == (m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) + +m.fs.R101.conversion.fix(0.75) +m.fs.R101.heat_duty.fix(0) + +m.fs.F101.vap_outlet.temperature.fix(325.0) +m.fs.F101.deltaP.fix(0) + +m.fs.F102.vap_outlet.temperature.fix(375) +m.fs.F102.deltaP.fix(-200000) + +m.fs.S101.split_fraction[0, "purge"].fix(0.2) +m.fs.C101.outlet.pressure.fix(350000) + +from idaes.core.util.initialization import propagate_state + +print(f"The DOF is {degrees_of_freedom(m)} initially") +m.fs.s03_expanded.deactivate() +print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") +tear_guesses = { + "flow_mol_phase_comp": { + (0, "Liq", "benzene"): 1e-5, + (0, "Liq", "toluene"): 0.30, + (0, "Liq", "methane"): 1e-5, + (0, "Liq", "hydrogen"): 1e-5, + (0, "Vap", "benzene"): 1e-5, + (0, "Vap", "toluene"): 1e-5, + (0, "Vap", "methane"): 0.5, + (0, "Vap", "hydrogen"): 0.5, + }, + "temperature": {0: 303}, + "pressure": {0: 350000}, +} + +for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.s03.destination, k)[k1].fix(v1) + +DOF_initial = degrees_of_freedom(m) +# x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) +# x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) +# x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) +# x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) + +# p_sat_dewT_0 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['benzene']) +# p_sat_dewT_1 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['toluene']) +# p_sat_dewT_2 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['hydrogen']) +# p_sat_dewT_3 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['methane']) +# +# print(p_sat_dewT_0) +# print(p_sat_dewT_1) +# print(p_sat_dewT_2) +# print(p_sat_dewT_3) + + +# +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['benzene'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['toluene'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['hydrogen'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['methane'])) +# +# print(value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew['Vap', 'Liq'])) + +# P = value(m.fs.H101.control_volume.properties_out[0.0].pressure) +# +# print(P*(x_0/p_sat_dewT_0 + x_1/p_sat_dewT_1) - 1) + + +m.fs.H101.default_initializer().initialize(m.fs.H101, output_level=idaeslog.INFO_HIGH) # Initialize Heater +x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) +x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) +x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) +x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) + +T_dew = value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew) +T_bub = value(m.fs.H101.control_volume.properties_out[0.0].temperature_bubble) +P_dew = value(m.fs.H101.control_volume.properties_out[0.0].pressure_dew) +P_bub = value(m.fs.H101.control_volume.properties_out[0.0].pressure_bubble) + +m.fs.H101.default_initializer().initialize(m.fs.H101) +propagate_state(m.fs.s04) # Establish connection between Heater and Reactor +m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor +propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit +m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit +propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter +propagate_state(m.fs.s07) +m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter +propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor +m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor +propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer +m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet +propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer +m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet +propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer +m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer +propagate_state(m.fs.s03) # Establish connection between Mixer and Heater +m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit +propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product +propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product +propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product + + +optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 300, + "tol": 1e-8, +} +solver = get_solver(options=optarg) +results = solver.solve(m, tee=True) + + +for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.H101.inlet, k)[k1].unfix() + +m.fs.s03_expanded.activate() +print( + f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" +) +#%% md +# ## 6 Solving the Model +#%% md +# We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html +#%% +optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 1000, + "tol": 1e-8, +} +#%% md +#
+# Inline Exercise: +# Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following: +# +# solver = get_solver(solver_options=optarg)
+# results = solver.solve(m, tee=True) +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+# +#%% +# Create the solver object + +# Solve the model +#%% +# Create the solver object +solver = get_solver(solver_options=optarg) + +# Solve the model +results = solver.solve(m, tee=True) +#%% +# Check solver solve status +from pyomo.environ import TerminationCondition + +assert results.solver.termination_condition == TerminationCondition.optimal +#%% md +# ## 7 Analyze the results +# +# +# +#%% md +# If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window. +# +#%% +# m.fs.visualize("HDA-Flowsheet") +#%% md +# Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display. +#%% +m.fs.report() +#%% md +# What is the total operating cost? +#%% +print("operating cost = $", value(m.fs.operating_cost)) +#%% +import pytest + +assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3) +#%% md +# For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method. +#%% +m.fs.F102.report() + +print() +print("benzene purity = ", value(m.fs.purity)) +#%% +assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) +assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3) +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) +#%% md +# Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101. +#%% +from idaes.core.util.tables import ( + create_stream_table_dataframe, + stream_table_dataframe_to_string, +) + +st = create_stream_table_dataframe({"Reactor": m.fs.s05, "Light Gases": m.fs.s06}) +print(stream_table_dataframe_to_string(st)) +#%% md +# ## 8 Optimization +# +# +# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. +# +# Let us try to minimize this cost such that: +# - we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream +# - purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80% +# - restricting the benzene loss in F101 vapor outlet to less than 20% +# +# For this problem, our decision variables are as follows: +# - H101 outlet temperature +# - R101 cooling duty provided +# - F101 outlet temperature +# - F102 outlet temperature +# - F102 deltaP in the flash tank +# +#%% md +# Let us declare our objective function for this problem. +#%% +m.fs.objective = Objective(expr=m.fs.operating_cost) +#%% md +# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. +#%% +m.fs.H101.outlet.temperature.unfix() +m.fs.R101.heat_duty.unfix() +m.fs.F101.vap_outlet.temperature.unfix() +m.fs.F102.vap_outlet.temperature.unfix() +#%% md +#
+# Inline Exercise: +# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+# +# +#%% +# Todo: Unfix deltaP for F102 +#%% +# Todo: Unfix deltaP for F102 +m.fs.F102.deltaP.unfix() +#%% +assert degrees_of_freedom(m) == 5 +#%% md +# Next, we need to set bounds on these decision variables to values shown below: +# +# - H101 outlet temperature [500, 600] K +# - R101 outlet temperature [600, 800] K +# - F101 outlet temperature [298, 450] K +# - F102 outlet temperature [298, 450] K +# - F102 outlet pressure [105000, 110000] Pa +# +# Let us first set the variable bound for the H101 outlet temperature as shown below: +#%% +m.fs.H101.outlet.temperature[0].setlb(500) +m.fs.H101.outlet.temperature[0].setub(600) +#%% md +#
+# Inline Exercise: +# Now, set the variable bound for the R101 outlet temperature. +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+#%% +# Todo: Set the bounds for reactor outlet temperature +#%% +# Todo: Set the bounds for reactor outlet temperature +m.fs.R101.outlet.temperature[0].setlb(600) +m.fs.R101.outlet.temperature[0].setub(800) +#%% md +# Let us fix the bounds for the rest of the decision variables. +#%% +m.fs.F101.vap_outlet.temperature[0].setlb(298.0) +m.fs.F101.vap_outlet.temperature[0].setub(450.0) +m.fs.F102.vap_outlet.temperature[0].setlb(298.0) +m.fs.F102.vap_outlet.temperature[0].setub(450.0) +m.fs.F102.vap_outlet.pressure[0].setlb(105000) +m.fs.F102.vap_outlet.pressure[0].setub(110000) +#%% md +# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. +#%% +m.fs.overhead_loss = Constraint( + expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "benzene"] +) +#%% md +#
+# Inline Exercise: +# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+#%% +# Todo: Add minimum product flow constraint +#%% +# Todo: Add minimum product flow constraint +m.fs.product_flow = Constraint( + expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] >= 0.15 +) +#%% md +# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. +#%% +m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) +#%% md +# +# We have now defined the optimization problem and we are now ready to solve this problem. +# +# +# +#%% +results = solver.solve(m, tee=True) +#%% +# Check for solver solve status +from pyomo.environ import TerminationCondition + +assert results.solver.termination_condition == TerminationCondition.optimal +#%% md +# ### 8.1 Optimization Results +# +# Display the results and product specifications +#%% +print("operating cost = $", value(m.fs.operating_cost)) + +print() +print("Product flow rate and purity in F102") + +m.fs.F102.report() + +print() +print("benzene purity = ", value(m.fs.purity)) + +print() +print("Overhead loss in F101") +m.fs.F101.report() +#%% +assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3) +assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) +#%% md +# Display optimal values for the decision variables +#%% +print( + f"""Optimal Values: + +H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K + +R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K + +F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K + +F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K +F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa +""" +) +#%% +assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) +assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) +assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3) +assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) \ No newline at end of file From c82abda0734e0460f893f5076ac59ec83a07cd14 Mon Sep 17 00:00:00 2001 From: Sufi Kaur <56102473+sufikaur@users.noreply.github.com> Date: Fri, 12 Sep 2025 18:45:00 -0700 Subject: [PATCH 15/36] Update depreciated github artifact actions v3 to current v4 (#149) * update to v4 * make names for each run be unique * make names for each run be unique with py version being tested * change naming mechanism to be more unique * experimenting with overwrite * mimic changes that worked one year ago by tanner * switch back to 22.04 * trying if this version will have the tests work * make name unique --------- Co-authored-by: Sufi Kaur --- .github/workflows/core.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 0151406d..3ac8d2a4 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -88,7 +88,7 @@ jobs: - win64 include: - os: linux - runner-image: ubuntu-20.04 + runner-image: ubuntu-22.04 - os: win64 runner-image: windows-2022 steps: @@ -112,7 +112,7 @@ jobs: pytest -v idaes_examples --ignore=idaes_examples/notebooks/docs/surrogates/sco2/alamo/ - name: Upload pytest-xdist worker logs if: success() || failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: pytest_worker_logs + name: pytest_worker_logs--${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}-${{ runner.os }}-py${{ matrix.python-version }} path: "tests_*.log" From d7d6f23b76a7659846a077d5029f8393a1393b1c Mon Sep 17 00:00:00 2001 From: dallan-keylogic <88728506+dallan-keylogic@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:27:21 -0400 Subject: [PATCH 16/36] tiny fix (#147) Co-authored-by: Keith Beattie --- idaes_examples/mod/hda/hda_ideal_VLE.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idaes_examples/mod/hda/hda_ideal_VLE.py b/idaes_examples/mod/hda/hda_ideal_VLE.py index b6c3207e..08bcc3d7 100644 --- a/idaes_examples/mod/hda/hda_ideal_VLE.py +++ b/idaes_examples/mod/hda/hda_ideal_VLE.py @@ -550,7 +550,7 @@ def fix_initialization_states(blk): # Also need to deactivate sum of mole fraction constraint for k in blk.values(): - if not k.config.defined_state: + if not k.config.defined_state and k.config.has_phase_equilibrium: k.equilibrium_constraint.deactivate() From 4028e8a4e791c1943f3ee5cffe3c15d23303b34b Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Wed, 1 Oct 2025 11:44:39 -0600 Subject: [PATCH 17/36] September Typos update --- .../archive/matopt/bimetallic_nanocluster_design_src.ipynb | 2 +- idaes_examples/archive/matopt/surface_design_src.ipynb | 2 +- idaes_examples/archive/power_gen/sofc/sofc.py | 2 +- idaes_examples/mod/hda/hda_ideal_VLE.py | 2 +- idaes_examples/mod/methanol/methanol_state_block_VLE.py | 2 +- idaes_examples/mod/power_gen/steam_turbine.py | 2 +- idaes_examples/mod/properties/reaction_property_example.py | 2 +- .../notebooks/docs/flowsheets/hda_flowsheet_with_costing.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_costing_doc.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_costing_test.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_costing_usr.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_distillation.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_distillation_doc.ipynb | 2 +- .../flowsheets/hda_flowsheet_with_distillation_exercise.ipynb | 2 +- .../flowsheets/hda_flowsheet_with_distillation_solution.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_distillation_test.ipynb | 2 +- .../docs/flowsheets/hda_flowsheet_with_distillation_usr.ipynb | 2 +- idaes_examples/notebooks/docs/power_gen/ngcc/ngcc.ipynb | 2 +- idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_doc.ipynb | 2 +- idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_test.ipynb | 2 +- idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_usr.ipynb | 2 +- .../properties/custom/custom_reaction_property_packages.ipynb | 2 +- .../custom/custom_reaction_property_packages_doc.ipynb | 2 +- .../custom/custom_reaction_property_packages_test.ipynb | 2 +- .../custom/custom_reaction_property_packages_usr.ipynb | 2 +- .../notebooks/docs/properties/dictionary_txy_diagrams.ipynb | 2 +- .../notebooks/docs/properties/dictionary_txy_diagrams_doc.ipynb | 2 +- .../docs/properties/dictionary_txy_diagrams_test.ipynb | 2 +- .../notebooks/docs/properties/dictionary_txy_diagrams_usr.ipynb | 2 +- idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb | 2 +- idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb | 2 +- .../notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb | 2 +- .../notebooks/docs/tut/core/hda_flowsheet_solution.ipynb | 2 +- idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb | 2 +- idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb | 2 +- idaes_examples/notebooks/docs/unit_models/reactors/cstr.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/cstr_doc.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/cstr_test.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/cstr_usr.ipynb | 2 +- .../docs/unit_models/reactors/equilibrium_reactor.ipynb | 2 +- .../docs/unit_models/reactors/equilibrium_reactor_doc.ipynb | 2 +- .../docs/unit_models/reactors/equilibrium_reactor_test.ipynb | 2 +- .../docs/unit_models/reactors/equilibrium_reactor_usr.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/gibbs_reactor.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/gibbs_reactor_doc.ipynb | 2 +- .../docs/unit_models/reactors/gibbs_reactor_test.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/gibbs_reactor_usr.ipynb | 2 +- .../notebooks/docs/unit_models/reactors/plug_flow_reactor.ipynb | 2 +- .../docs/unit_models/reactors/plug_flow_reactor_doc.ipynb | 2 +- .../docs/unit_models/reactors/plug_flow_reactor_test.ipynb | 2 +- .../docs/unit_models/reactors/plug_flow_reactor_usr.ipynb | 2 +- .../docs/unit_models/reactors/stoichiometric_reactor.ipynb | 2 +- .../docs/unit_models/reactors/stoichiometric_reactor_doc.ipynb | 2 +- .../docs/unit_models/reactors/stoichiometric_reactor_test.ipynb | 2 +- .../docs/unit_models/reactors/stoichiometric_reactor_usr.ipynb | 2 +- 55 files changed, 55 insertions(+), 55 deletions(-) diff --git a/idaes_examples/archive/matopt/bimetallic_nanocluster_design_src.ipynb b/idaes_examples/archive/matopt/bimetallic_nanocluster_design_src.ipynb index a1872731..34461e29 100644 --- a/idaes_examples/archive/matopt/bimetallic_nanocluster_design_src.ipynb +++ b/idaes_examples/archive/matopt/bimetallic_nanocluster_design_src.ipynb @@ -199,7 +199,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To start, we inidcate that the choice to place an atom is fixed so that each canvas site is required to have an atom. This simplifies the problem significantly and results in a model that will seek to find the optimal labeling of metals on the nanocluster. " + "To start, we indicate that the choice to place an atom is fixed so that each canvas site is required to have an atom. This simplifies the problem significantly and results in a model that will seek to find the optimal labeling of metals on the nanocluster. " ] }, { diff --git a/idaes_examples/archive/matopt/surface_design_src.ipynb b/idaes_examples/archive/matopt/surface_design_src.ipynb index 49861f88..bfb00248 100644 --- a/idaes_examples/archive/matopt/surface_design_src.ipynb +++ b/idaes_examples/archive/matopt/surface_design_src.ipynb @@ -211,7 +211,7 @@ "source": [ "First, we introduce two rules to fix special sites in the design. \n", "We fix the bottom two layers of atoms to exist, creating underlying bulk layers above which we will introduce nanostruced defets.\n", - "We also fix an arbitrary atom in the top layer, breaking symmetry of the design space and resulting in easier to solve opitmization problems without actually restricting the designs that can be possibly represented. " + "We also fix an arbitrary atom in the top layer, breaking symmetry of the design space and resulting in easier to solve optimization problems without actually restricting the designs that can be possibly represented. " ] }, { diff --git a/idaes_examples/archive/power_gen/sofc/sofc.py b/idaes_examples/archive/power_gen/sofc/sofc.py index 036fd56c..34955f5c 100644 --- a/idaes_examples/archive/power_gen/sofc/sofc.py +++ b/idaes_examples/archive/power_gen/sofc/sofc.py @@ -849,7 +849,7 @@ def scale_flowsheet(m): m.fs.flash.control_volume.properties_out[0].mole_frac_comp, 1e1 ) - # hide missing scaling factor wornings + # hide missing scaling factor warnings scaling_log = idaeslog.getLogger("idaes.core.util.scaling", level=idaeslog.ERROR) iscale.calculate_scaling_factors(m) diff --git a/idaes_examples/mod/hda/hda_ideal_VLE.py b/idaes_examples/mod/hda/hda_ideal_VLE.py index 08bcc3d7..c6295a1c 100644 --- a/idaes_examples/mod/hda/hda_ideal_VLE.py +++ b/idaes_examples/mod/hda/hda_ideal_VLE.py @@ -11,7 +11,7 @@ # at the URL "https://github.com/IDAES/idaes-pse". ############################################################################## """ -Example ideal parameter block for the VLE calucations for a +Example ideal parameter block for the VLE calculations for a Benzene-Toluene-o-Xylene system. """ diff --git a/idaes_examples/mod/methanol/methanol_state_block_VLE.py b/idaes_examples/mod/methanol/methanol_state_block_VLE.py index bbcd02aa..7b20aacb 100644 --- a/idaes_examples/mod/methanol/methanol_state_block_VLE.py +++ b/idaes_examples/mod/methanol/methanol_state_block_VLE.py @@ -11,7 +11,7 @@ # at the URL "https://github.com/IDAES/idaes-pse". ############################################################################## """ -Property package for ideal VLE calucations for the methanol synthesis problem. +Property package for ideal VLE calculations for the methanol synthesis problem. Correlations from Turkay and Grossmann paper. See Latex files for details. """ diff --git a/idaes_examples/mod/power_gen/steam_turbine.py b/idaes_examples/mod/power_gen/steam_turbine.py index 8fac5472..43c9dc31 100644 --- a/idaes_examples/mod/power_gen/steam_turbine.py +++ b/idaes_examples/mod/power_gen/steam_turbine.py @@ -521,7 +521,7 @@ def _add_tags(self): format_string="{:.3f}", display_units=pyo.units.kJ / pyo.units.mol, ) - # Tag some important model quntities + # Tag some important model quantities self.tags = iutil.ModelTagGroup() self.tags["power"] = iutil.ModelTag( doc=f"Steam turbine electric power output", diff --git a/idaes_examples/mod/properties/reaction_property_example.py b/idaes_examples/mod/properties/reaction_property_example.py index 5c2f2475..812418c0 100644 --- a/idaes_examples/mod/properties/reaction_property_example.py +++ b/idaes_examples/mod/properties/reaction_property_example.py @@ -140,7 +140,7 @@ def build(self): units=pyunits.mol / pyunits.m**3 / pyunits.s / pyunits.Pa**2, ) - self.k_eq = Param(initialize=10000, doc="Equlibrium constant", units=pyunits.Pa) + self.k_eq = Param(initialize=10000, doc="Equilibrium constant", units=pyunits.Pa) self.reaction_rate = Var( self.params.rate_reaction_idx, diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing.ipynb index 656dc674..3ccbb247 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing.ipynb @@ -45,7 +45,7 @@ "\n", "- Import external pre-built steady-state flowsheets using the IDAES unit model library\n", "- Define and add costing blocks using the IDAES Process Costing Framework\n", - "- Fomulate and solve a process economics optimization problem\n", + "- Formulate and solve a process economics optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_doc.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_doc.ipynb index 0a6a239c..2ee4b7c8 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_doc.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_doc.ipynb @@ -45,7 +45,7 @@ "\n", "- Import external pre-built steady-state flowsheets using the IDAES unit model library\n", "- Define and add costing blocks using the IDAES Process Costing Framework\n", - "- Fomulate and solve a process economics optimization problem\n", + "- Formulate and solve a process economics optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_test.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_test.ipynb index feceb84b..c9068d48 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_test.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_test.ipynb @@ -45,7 +45,7 @@ "\n", "- Import external pre-built steady-state flowsheets using the IDAES unit model library\n", "- Define and add costing blocks using the IDAES Process Costing Framework\n", - "- Fomulate and solve a process economics optimization problem\n", + "- Formulate and solve a process economics optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_usr.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_usr.ipynb index 8c04460d..009608a6 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_usr.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_costing_usr.ipynb @@ -45,7 +45,7 @@ "\n", "- Import external pre-built steady-state flowsheets using the IDAES unit model library\n", "- Define and add costing blocks using the IDAES Process Costing Framework\n", - "- Fomulate and solve a process economics optimization problem\n", + "- Formulate and solve a process economics optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation.ipynb index 44e6cf27..3b7cb86a 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_doc.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_doc.ipynb index 1e23d2be..a336a020 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_doc.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_doc.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_exercise.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_exercise.ipynb index e44357de..176dabfd 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_exercise.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_exercise.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_solution.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_solution.ipynb index 86d59dd3..c1ecd91b 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_solution.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_solution.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_test.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_test.ipynb index ba91dc8e..5b9d2479 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_test.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_test.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_usr.ipynb b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_usr.ipynb index 86d59dd3..c1ecd91b 100644 --- a/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_usr.ipynb +++ b/idaes_examples/notebooks/docs/flowsheets/hda_flowsheet_with_distillation_usr.ipynb @@ -47,7 +47,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc.ipynb b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc.ipynb index 20fa0c26..1cbff717 100644 --- a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc.ipynb +++ b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc.ipynb @@ -2809,7 +2809,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Assert results approximately agree with baseline reoprt\n", + "# Assert results approximately agree with baseline report\n", "assert pyo.value(m.fs.net_power_mw[0]) == pytest.approx(646)\n", "assert pyo.value(m.fs.gross_power[0]) == pytest.approx(-690e6, rel=0.001)\n", "assert pyo.value(100 * m.fs.lhv_efficiency[0]) == pytest.approx(52.8, abs=0.1)\n", diff --git a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_doc.ipynb b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_doc.ipynb index 7127641c..7a76ae5d 100644 --- a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_doc.ipynb +++ b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_doc.ipynb @@ -2795,7 +2795,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Assert results approximately agree with baseline reoprt\n", + "# Assert results approximately agree with baseline report\n", "assert pyo.value(m.fs.net_power_mw[0]) == pytest.approx(646)\n", "assert pyo.value(m.fs.gross_power[0]) == pytest.approx(-690e6, rel=0.001)\n", "assert pyo.value(100 * m.fs.lhv_efficiency[0]) == pytest.approx(52.8, abs=0.1)\n", diff --git a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_test.ipynb b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_test.ipynb index 7127641c..7a76ae5d 100644 --- a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_test.ipynb +++ b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_test.ipynb @@ -2795,7 +2795,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Assert results approximately agree with baseline reoprt\n", + "# Assert results approximately agree with baseline report\n", "assert pyo.value(m.fs.net_power_mw[0]) == pytest.approx(646)\n", "assert pyo.value(m.fs.gross_power[0]) == pytest.approx(-690e6, rel=0.001)\n", "assert pyo.value(100 * m.fs.lhv_efficiency[0]) == pytest.approx(52.8, abs=0.1)\n", diff --git a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_usr.ipynb b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_usr.ipynb index 7127641c..7a76ae5d 100644 --- a/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_usr.ipynb +++ b/idaes_examples/notebooks/docs/power_gen/ngcc/ngcc_usr.ipynb @@ -2795,7 +2795,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Assert results approximately agree with baseline reoprt\n", + "# Assert results approximately agree with baseline report\n", "assert pyo.value(m.fs.net_power_mw[0]) == pytest.approx(646)\n", "assert pyo.value(m.fs.gross_power[0]) == pytest.approx(-690e6, rel=0.001)\n", "assert pyo.value(100 * m.fs.lhv_efficiency[0]) == pytest.approx(52.8, abs=0.1)\n", diff --git a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages.ipynb b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages.ipynb index 5a825d3e..372896df 100644 --- a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages.ipynb +++ b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages.ipynb @@ -406,7 +406,7 @@ " units=pyunits.mol / pyunits.m**3 / pyunits.s,\n", " )\n", "\n", - " self.k_eq = Param(initialize=10000, doc=\"Equlibrium constant\", units=pyunits.Pa)" + " self.k_eq = Param(initialize=10000, doc=\"Equilibrium constant\", units=pyunits.Pa)" ] }, { diff --git a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_doc.ipynb b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_doc.ipynb index de3ceedd..46bf3342 100644 --- a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_doc.ipynb +++ b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_doc.ipynb @@ -414,7 +414,7 @@ " units=pyunits.mol / pyunits.m**3 / pyunits.s,\n", " )\n", "\n", - " self.k_eq = Param(initialize=10000, doc=\"Equlibrium constant\", units=pyunits.Pa)" + " self.k_eq = Param(initialize=10000, doc=\"Equilibrium constant\", units=pyunits.Pa)" ] }, { diff --git a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_test.ipynb b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_test.ipynb index e9f5b157..7b07c6d2 100644 --- a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_test.ipynb +++ b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_test.ipynb @@ -406,7 +406,7 @@ " units=pyunits.mol / pyunits.m**3 / pyunits.s,\n", " )\n", "\n", - " self.k_eq = Param(initialize=10000, doc=\"Equlibrium constant\", units=pyunits.Pa)" + " self.k_eq = Param(initialize=10000, doc=\"Equilibrium constant\", units=pyunits.Pa)" ] }, { diff --git a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_usr.ipynb b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_usr.ipynb index 00d5caa2..455f0384 100644 --- a/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_usr.ipynb +++ b/idaes_examples/notebooks/docs/properties/custom/custom_reaction_property_packages_usr.ipynb @@ -406,7 +406,7 @@ " units=pyunits.mol / pyunits.m**3 / pyunits.s,\n", " )\n", "\n", - " self.k_eq = Param(initialize=10000, doc=\"Equlibrium constant\", units=pyunits.Pa)" + " self.k_eq = Param(initialize=10000, doc=\"Equilibrium constant\", units=pyunits.Pa)" ] }, { diff --git a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams.ipynb b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams.ipynb index b7e1a3cb..290f3e13 100644 --- a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams.ipynb +++ b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams.ipynb @@ -295,7 +295,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the sacling factor be sure to reed the documentation/examples of the scaling tools." + "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the scaling factor be sure to reed the documentation/examples of the scaling tools." ] }, { diff --git a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_doc.ipynb b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_doc.ipynb index 91726cfe..bf8d9700 100644 --- a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_doc.ipynb +++ b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_doc.ipynb @@ -295,7 +295,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the sacling factor be sure to reed the documentation/examples of the scaling tools." + "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the scaling factor be sure to reed the documentation/examples of the scaling tools." ] }, { diff --git a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_test.ipynb b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_test.ipynb index 4117f832..b8e76751 100644 --- a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_test.ipynb +++ b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_test.ipynb @@ -295,7 +295,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the sacling factor be sure to reed the documentation/examples of the scaling tools." + "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the scaling factor be sure to reed the documentation/examples of the scaling tools." ] }, { diff --git a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_usr.ipynb b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_usr.ipynb index 4117f832..b8e76751 100644 --- a/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_usr.ipynb +++ b/idaes_examples/notebooks/docs/properties/dictionary_txy_diagrams_usr.ipynb @@ -295,7 +295,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the sacling factor be sure to reed the documentation/examples of the scaling tools." + "There will be a WARNING from missing scaling factors. This is normal as the Txy diagram function does not know the state definition being used. To learn more about the scaling factor be sure to reed the documentation/examples of the scaling tools." ] }, { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index a7645f92..4f11e1c6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 2d862e0d..86569f0e 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index bcdc90bb..ef8abc44 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 6f8b47f4..088af81e 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 415cf48c..83d872c4 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 6f8b47f4..088af81e 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -42,7 +42,7 @@ "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/cstr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/cstr.ipynb index 0d0fc742..f6635a4a 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/cstr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/cstr.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES CSTR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_doc.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_doc.ipynb index 891c3495..0df12dce 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_doc.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_doc.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES CSTR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_test.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_test.ipynb index a77d3809..f552f10e 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_test.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_test.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES CSTR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_usr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_usr.ipynb index 946169b9..6c22e990 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/cstr_usr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/cstr_usr.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES CSTR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor.ipynb index e8b02ceb..a1f8fd24 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES EquilibriumReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_doc.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_doc.ipynb index bafa95cf..55632a3d 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_doc.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_doc.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES EquilibriumReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_test.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_test.ipynb index a845483e..666ce9ca 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_test.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_test.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES EquilibriumReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_usr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_usr.ipynb index 6185b931..c0231679 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_usr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/equilibrium_reactor_usr.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES EquilibriumReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor.ipynb index da52dcfb..51e646fa 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES GibbsReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_doc.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_doc.ipynb index 069a9a84..372155e6 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_doc.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_doc.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES GibbsReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_test.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_test.ipynb index 7a9cba50..b9a12337 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_test.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_test.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES GibbsReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_usr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_usr.ipynb index b7984618..119dcb5f 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_usr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/gibbs_reactor_usr.ipynb @@ -42,7 +42,7 @@ "- Call and implement the IDAES GibbsReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor.ipynb index 989a3458..fbe3f8a2 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES PFR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_doc.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_doc.ipynb index 05620386..6b753730 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_doc.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_doc.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES PFR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_test.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_test.ipynb index 76d32312..dceac03b 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_test.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_test.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES PFR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_usr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_usr.ipynb index 30984465..da555ce7 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_usr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/plug_flow_reactor_usr.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES PFR unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor.ipynb index b0ed3611..2335f6a4 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES StochiometricReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_doc.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_doc.ipynb index 99443416..d8a8866f 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_doc.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_doc.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES StochiometricReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_test.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_test.ipynb index 675c7fea..4135cb99 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_test.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_test.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES StochiometricReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", diff --git a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_usr.ipynb b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_usr.ipynb index 5660e55a..3ce8eb06 100644 --- a/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_usr.ipynb +++ b/idaes_examples/notebooks/docs/unit_models/reactors/stoichiometric_reactor_usr.ipynb @@ -41,7 +41,7 @@ "- Call and implement the IDAES StochiometricReactor unit model\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", "- Connecting unit models in a flowsheet using Arcs\n", - "- Fomulate and solve an optimization problem\n", + "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", " - Adding additional constraints \n", From adebd0cd5263ddf1f55c4c6ee1b1cb63ecd085b3 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Wed, 1 Oct 2025 11:50:34 -0600 Subject: [PATCH 18/36] Add diff to job, fix black formatting --- .github/workflows/core.yml | 2 +- idaes_examples/mod/properties/reaction_property_example.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 3ac8d2a4..1dfde479 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -59,7 +59,7 @@ jobs: pip install --progress-bar off black[jupyter]==24.3.0 - name: Run Black to verify that the committed code is formatted run: | - black --check . + black --check --diff . spell-check: name: Check Spelling diff --git a/idaes_examples/mod/properties/reaction_property_example.py b/idaes_examples/mod/properties/reaction_property_example.py index 812418c0..64db60e3 100644 --- a/idaes_examples/mod/properties/reaction_property_example.py +++ b/idaes_examples/mod/properties/reaction_property_example.py @@ -140,7 +140,9 @@ def build(self): units=pyunits.mol / pyunits.m**3 / pyunits.s / pyunits.Pa**2, ) - self.k_eq = Param(initialize=10000, doc="Equilibrium constant", units=pyunits.Pa) + self.k_eq = Param( + initialize=10000, doc="Equilibrium constant", units=pyunits.Pa + ) self.reaction_rate = Var( self.params.rate_reaction_idx, From 64fd034f076e43ec4f0c653ce0f92a6bc928591b Mon Sep 17 00:00:00 2001 From: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> Date: Thu, 2 Oct 2025 09:05:31 -0600 Subject: [PATCH 19/36] Add in a weekly scheduled job to make sure no spurious failures are introduced --- .github/workflows/core.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 1dfde479..c9c7e1bf 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -4,6 +4,9 @@ on: push: branches: - main + schedule: + # run Sundays at 3:00 am UTC (10 pm ET/7 pm PT) + - cron: '0 3 * * 0' repository_dispatch: # to run this, send a POST API call at repos/IDAES/idaes-pse/dispatches with the specified event_type # e.g. `gh repos/IDAES/idaes-pse/dispatches -F event_type=ci_run_tests` From c642150af0b1cbb14b728133bbb9489f2848f396 Mon Sep 17 00:00:00 2001 From: Sufi Kaur Date: Fri, 3 Oct 2025 12:13:52 -0700 Subject: [PATCH 20/36] 2.10.dev0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2323b329..fcb8c893 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" name = "idaes-examples" description = "IDAES Process Systems Engineering Examples" readme = "README.md" -version = "2.8.dev0" +version = "2.10.dev0" license = {text="BSD"} requires-python = ">=3.9" authors = [ From 0b4c00b8d915845406f1836980b69ab0989e5682 Mon Sep 17 00:00:00 2001 From: Alex Dowling Date: Thu, 9 Oct 2025 14:50:28 -0400 Subject: [PATCH 21/36] Improve welcome to IDAES background material (#146) * Added links and references to background material * Forgot to save changes * Apply suggestions from code review Co-authored-by: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> --------- Co-authored-by: Keith Beattie Co-authored-by: Bethany Nicholson Co-authored-by: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> --- idaes_examples/notebooks/index.md | 6 +++- idaes_examples/notebooks/references.bib | 41 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/idaes_examples/notebooks/index.md b/idaes_examples/notebooks/index.md index 606a8a8e..b0bb00a3 100644 --- a/idaes_examples/notebooks/index.md +++ b/idaes_examples/notebooks/index.md @@ -25,11 +25,15 @@ The online examples have been created with the ### Prerequisites -Examples in this documentation are rigorously *tested* to ensure that they work with the *latest* version of the IDAES +**Install the latest version of IDAES.** Examples in this documentation are rigorously *tested* to ensure that they work with the *latest* version of the IDAES software. For more information on installing IDAES on your platform, please refer to the [IDAES documentation](https://idaes-pse.readthedocs.io/en/latest/index.html). +**Learn about mathematical optimization and Pyomo.** IDAES is a state-of-the-art equation-oriented modeling and optimization environment. Below are recommended topics and references: +* *Mathematical optimization* especially nonlinear programs (optimization problems) and chemical engineering applications. {cite}`Postek2025`, along with the [companion website](https://mobook.github.io/MO-book/intro.html) and [overview video](https://www.youtube.com/watch?v=DPv-7TeSTNs), are the best resources for a user new to mathematical optimization. {cite}`biegler1997systematic`, {cite}`biegler2010nonlinear`, and {cite}`grossmann2021advanced` are excellent references for advanced users. [Professor Alexander Dowling's course website](https://ndcbe.github.io/optimization/intro.html) includes Jupyter notebooks and Pyomo examples inspired by these texts. +* *Pyomo*. IDAES is built upon Pyomo, which is an open-source algebraic modeling environment. New users will likely find {cite}`Postek2025` along with its [companion website](https://mobook.github.io/MO-book/intro.html) and the [ND Pyomo Cookbook](https://ndcbe.github.io/ND-Pyomo-Cookbook/README.html), as the easiest introduction to Pyomo. Other excellent resources include {cite}`bynum2021pyomo` and the official [Pyomo documentation](https://pyomo.readthedocs.io/en/stable/). + ### Getting the source code The full source code for these examples is available from the [IDAES examples repository](https://github.com/IDAES/examples) on GitHub. diff --git a/idaes_examples/notebooks/references.bib b/idaes_examples/notebooks/references.bib index ea7b27b2..dc30276e 100644 --- a/idaes_examples/notebooks/references.bib +++ b/idaes_examples/notebooks/references.bib @@ -14,4 +14,45 @@ @incollection{miller2018idaes Bethany Nicholson and Carl Laird and Lorenz T. Biegler and Debangsu Bhattacharyya and Nikolaos V. Sahinidis and Ignacio E. Grossmann and Chrysanthos E. Gounaris and Dan Gunter}, keywords = {Multiscale modeling, conceptual design, process optimization, dynamic optimization, parameter estimation} +} + +@book{Postek2025, + title = {Hands-On Mathematical Optimization with Python}, + author = { Krzysztof Postek and Alessandro Zocca and Vrije Universiteit Amsterdam and Joaquim A. S. Gromicho}, + publisher = {Cambridge University Press}, + year = {2025}, + isbn = {9781009493505}, + url = {https://www.cambridge.org/us/universitypress/subjects/mathematics/optimization-or-and-risk-analysis/hands-mathematical-optimization-python} +} + +@book{biegler1997systematic, + title={Systematic methods of chemical process design}, + author={Biegler, Lorenz T and Grossmann, Ignacio E and Westerberg, Arthur W}, + year={1997}, + publisher={Prentice Hall}, + isbn={9780134924229} +} + +@book{biegler2010nonlinear, + title={Nonlinear programming: concepts, algorithms, and applications to chemical processes}, + author={Biegler, Lorenz T}, + year={2010}, + publisher={SIAM} +} + +@book{grossmann2021advanced, + title={Advanced optimization for process systems engineering}, + author={Grossmann, Ignacio E}, + year={2021}, + publisher={Cambridge University Press}, + isbn = {9781108831659} +} + +@book{bynum2021pyomo, + title={Pyomo-optimization modeling in python}, + author={Bynum, Michael L and Hackebeil, Gabriel A and Hart, William E and Laird, Carl D and Nicholson, Bethany L and Siirola, John D and Watson, Jean-Paul and Woodruff, David L and others}, + volume={67}, + number={s 32}, + year={2021}, + publisher={Springer} } \ No newline at end of file From 5d9930c0a2dbaa5a5ceb38492a004fda78c1a438 Mon Sep 17 00:00:00 2001 From: Dan Gunter Date: Thu, 30 Oct 2025 11:21:03 -0700 Subject: [PATCH 22/36] fixes flexbox settings for HDA flowsheet (#152) --- idaes_examples/notebooks/_static/custom.css | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 idaes_examples/notebooks/_static/custom.css diff --git a/idaes_examples/notebooks/_static/custom.css b/idaes_examples/notebooks/_static/custom.css new file mode 100644 index 00000000..fd822f3d --- /dev/null +++ b/idaes_examples/notebooks/_static/custom.css @@ -0,0 +1,8 @@ +/* Custom CSS for IDAES Examples */ + +/* For some reason this is needed */ +.bd-main .bd-content { + flex-direction: column; + flex-wrap: nowrap; +} + From 3e345828d810d589f72e2783cffa485976fb9736 Mon Sep 17 00:00:00 2001 From: dallan-keylogic <88728506+dallan-keylogic@users.noreply.github.com> Date: Thu, 30 Oct 2025 15:45:38 -0400 Subject: [PATCH 23/36] Fix SOC dynamics failure (#150) * New notebook soc_pid_con in directory docs/power_gen/solid_oxide_cell * Preliminary work on getting notebook ready. * bring pid example up to date * remember to save * do preprocessing * add soc_dynamic_flowsheet.svg to gitignore * make gitignore and checking results work * delete wrong flowsheet * update initial conditions * delete irrelevant file * update to merged crossflow_hx nomenclature * run idaesx pre * New notebook soc_steady_state_optimiza in directory docs/power_gen/solid_oxide_cell * steady state optimization * changes * new setpoint files * changes * fixes * optimization * experiments * merge cleanup * lower expectations * blah * bring in line with main * changes due to xflowhx fix * get changes from latest version of flowsheet * fix remaining issues with flowsheet * move LL deactivation * remember to commit jsons * optimization example not yet ready * black and install from PR * did the child notebooks not get updated? --------- Co-authored-by: Ludovico Bianchi Co-authored-by: Keith Beattie --- README-developer.md | 2 +- .../mod/power_gen/soc_dynamic_flowsheet.py | 259 +- .../solid_oxide_cell/max_production.json.gz | Bin 250345 -> 213722 bytes .../solid_oxide_cell/min_production.json.gz | Bin 0 -> 213686 bytes .../solid_oxide_cell/neutral.json.gz | Bin 0 -> 249222 bytes .../solid_oxide_cell/power_mode.json.gz | Bin 250441 -> 214095 bytes .../solid_oxide_cell/soc_pid_control.ipynb | 1278 ++--- .../soc_pid_control_doc.ipynb | 4973 ++++++++-------- .../soc_pid_control_test.ipynb | 5073 ++++++++--------- .../soc_pid_control_usr.ipynb | 4973 ++++++++-------- .../soec_flowsheet_operating_conditions.csv | 4 +- requirements-dev.txt | 3 +- 12 files changed, 8212 insertions(+), 8353 deletions(-) create mode 100644 idaes_examples/notebooks/docs/power_gen/solid_oxide_cell/min_production.json.gz create mode 100644 idaes_examples/notebooks/docs/power_gen/solid_oxide_cell/neutral.json.gz diff --git a/README-developer.md b/README-developer.md index 0ab7bb68..c2c02a9d 100644 --- a/README-developer.md +++ b/README-developer.md @@ -23,7 +23,7 @@ Clone the repository from GitHub, set up your Python environment as you usually pip install -r requirements-dev.txt ``` -Note: if you have IDAES installed in your current environment, it will uninstall it and install the latest version from the main branch on Github. You can run `pip uninstall idaes` and reinstall it from your local repository if you need to test examples against a local branch of IDAES. +Note: if you have IDAES installed in your current environment, it will uninstall it and install the latest version from the main branch on Github. You can run `pip uninstall idaes-pse` and reinstall it from your local repository if you need to test examples against a local branch of IDAES. The configuration of the installation is stored in `pyproject.toml`. diff --git a/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py b/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py index 60e5c867..a2744713 100644 --- a/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py +++ b/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py @@ -3,7 +3,7 @@ import numpy as np import pyomo.environ as pyo -from pyomo.common.config import ConfigValue, Bool +from pyomo.common.config import ConfigValue, Bool, ListOf from pyomo.network import Arc from pyomo.common.fileutils import this_file_dir @@ -83,6 +83,16 @@ class SocStandaloneFlowsheetData(FlowsheetBlockData): **False** - do not make interconnect.}""", ), ) + CONFIG.declare( + "soc_zfaces", + ConfigValue( + default=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], + domain=ListOf(float), + description="List containing coordinates of control volume faces " + "in z direction. Coordinates must start with zero, be strictly " + "increasing, and end with one", + ), + ) CONFIG.declare( "quasi_steady_state", ConfigValue( @@ -96,6 +106,19 @@ class SocStandaloneFlowsheetData(FlowsheetBlockData): **False** - Create dynamic unit models where appropriate.}""", ), ) + CONFIG.declare( + "soc_heat_loss", + ConfigValue( + default=False, + domain=Bool, + description="If True, add heat loss term to the SOC", + doc="""If True, add heat loss term to the SOC, + **default** - False. + **Valid values:** { + **True** - Heat loss term for the SOC, + **False** - No heat loss term created in SOC.}""", + ), + ) def build(self): super().build() @@ -328,7 +351,7 @@ def _define_cell_params(self): soec.interconnect.resistivity_thermal_exponent_dividend.fix(0) def _add_units(self): - zfaces = np.linspace(0, 1, 11).tolist() + zfaces = self.config.soc_zfaces xfaces_electrode = [0.0, 1.0] xfaces_electrolyte = [0.0, 1.0] @@ -397,6 +420,7 @@ def _add_units(self): solid_oxide_cell_config=soc_cell_config, fuel_property_package=self.h2_side_prop_params, oxygen_property_package=self.o2_side_prop_params, + has_heat_loss_term=self.config.soc_heat_loss, ) self.sweep_recycle_split = gum.Separator( @@ -439,20 +463,21 @@ def pressure_equality_eqn(b, t): "dynamic": False, "has_holdup": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, hot_side={ "property_package": self.o2_side_prop_params, "dynamic": False, "has_holdup": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, shell_is_hot=True, flow_type=HeatExchangerFlowPattern.countercurrent, - finite_elements=10, + finite_elements=6, + collocation_points=1, tube_arrangement="in-line", ) self.feed_hot_exchanger = CrossFlowHeatExchanger1D( @@ -463,20 +488,21 @@ def pressure_equality_eqn(b, t): "has_holdup": False, "dynamic": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, hot_side={ "property_package": self.h2_side_prop_params, "has_holdup": False, "dynamic": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, shell_is_hot=True, flow_type=HeatExchangerFlowPattern.countercurrent, - finite_elements=12, + finite_elements=6, + collocation_points=1, tube_arrangement="staggered", ) self.feed_medium_exchanger = CrossFlowHeatExchanger1D( @@ -487,22 +513,28 @@ def pressure_equality_eqn(b, t): "has_holdup": False, "dynamic": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, hot_side={ "property_package": self.o2_side_prop_params, "has_holdup": False, "dynamic": False, "has_pressure_change": False, - "transformation_method": "dae.finite_difference", - "transformation_scheme": "BACKWARD", + "transformation_method": "dae.collocation", + "transformation_scheme": "LAGRANGE-LEGENDRE", }, shell_is_hot=True, finite_elements=6, + collocation_points=1, flow_type=HeatExchangerFlowPattern.countercurrent, tube_arrangement="staggered", ) + # Need to deactivate unnecessary equations for LL collocation + self.sweep_exchanger.lagrange_legendre_deactivation() + self.feed_medium_exchanger.lagrange_legendre_deactivation() + self.feed_hot_exchanger.lagrange_legendre_deactivation() + self.sweep_blower = gum.Compressor( doc="Sweep blower", property_package=self.o2_side_prop_params, dynamic=False ) @@ -512,7 +544,10 @@ def pressure_equality_eqn(b, t): dynamic=dynamic_unit_models, has_fluid_holdup=False, has_pressure_change=False, - finite_elements=4, + transformation_method="dae.collocation", + transformation_scheme="LAGRANGE-RADAU", + finite_elements=2, + collocation_points=2, tube_arrangement="in-line", ) self.sweep_heater = Heater1D( @@ -521,7 +556,10 @@ def pressure_equality_eqn(b, t): dynamic=dynamic_unit_models, has_fluid_holdup=False, has_pressure_change=False, - finite_elements=4, + transformation_method="dae.collocation", + transformation_scheme="LAGRANGE-RADAU", + finite_elements=2, + collocation_points=2, tube_arrangement="in-line", ) self.condenser_flash = gum.Flash( @@ -749,73 +787,94 @@ def total_electric_power_eqn(b, t): self.time, initialize=1000, units=pyo.units.K ) + z0 = self.soc_module.solid_oxide_cell.iznodes.first() + zend = self.soc_module.solid_oxide_cell.iznodes.last() + @self.Constraint(self.time) def stack_fuel_inlet_temperature_eqn(b, t): return ( b.stack_fuel_inlet_temperature[t] - == b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, 1] + == b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, z0] ) @self.Constraint(self.time) def stack_sweep_inlet_temperature_eqn(b, t): return ( b.stack_sweep_inlet_temperature[t] - == b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, 10] + == b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, zend] ) @self.Constraint(self.time) def stack_core_temperature_eqn(b, t): - return ( - b.stack_core_temperature[t] - == ( - b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, 5] - + b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, 6] + iznodes = self.soc_module.solid_oxide_cell.iznodes + if len(iznodes) % 2 == 0: + zlo = len(iznodes) / 2 + zhi = len(iznodes) / 2 + 1 + return ( + b.stack_core_temperature[t] + == ( + b.soc_module.solid_oxide_cell.interconnect.temperature[ + t, 1, zlo + ] + + b.soc_module.solid_oxide_cell.interconnect.temperature[ + t, 1, zhi + ] + ) + / 2 + ) + else: + zmid = pyo.ceil(len(iznodes) / 2) + return b.stack_core_temperature[t] == ( + b.soc_module.solid_oxide_cell.interconnect.temperature[t, 1, zmid] ) - / 2 - ) def _scaling(self): ssf = iscale.set_scaling_factor cst = iscale.constraint_scaling_transform - - ssf(self.total_electric_power, 1e-8) - ssf(self.soec_water_consumption_rate, 1e-3) - ssf(self.feed_recycle_split.recycle_ratio, 1) - ssf(self.sweep_recycle_split.recycle_ratio, 1) - ssf(self.condenser_split.recycle_ratio, 1) - ssf(self.h2_mass_production, 1) - scale_indexed_constraint(self.total_electric_power_eqn, 1e-8) scale_indexed_constraint(self.soec_water_consumption_rate_eqn, 1e-3) - - ssf(self.condenser_flash.control_volume.heat, 1e-7) - ssf(self.feed_heater.control_volume.area, 1e-1) ssf(self.sweep_heater.control_volume.area, 1e-1) - ssf(self.feed_heater.control_volume.heat, 1e-6) - ssf(self.feed_heater.electric_heat_duty, 1e-6) - ssf(self.feed_heater.control_volume._enthalpy_flow, 1e-8) - ssf(self.feed_heater.control_volume.enthalpy_flow_dx, 1e-7) - ssf(self.feed_heater.heat_holdup, 1e-9) - - ssf(self.sweep_heater.control_volume.heat, 1e-6) - ssf(self.sweep_heater.electric_heat_duty, 1e-6) - ssf(self.sweep_heater.control_volume._enthalpy_flow, 1e-8) - ssf(self.sweep_heater.control_volume.enthalpy_flow_dx, 1e-7) - ssf(self.sweep_heater.heat_holdup, 1e-9) + for t in self.time: + ssf(self.total_electric_power[t], 1e-8) + ssf(self.soec_water_consumption_rate[t], 1e-3) + ssf(self.feed_recycle_split.recycle_ratio[t], 1) + ssf(self.sweep_recycle_split.recycle_ratio[t], 1) + ssf(self.condenser_split.recycle_ratio[t], 1) + ssf(self.h2_mass_production[t], 1) + + ssf(self.condenser_flash.control_volume.heat[t], 1e-7) + + ssf(self.feed_heater.electric_heat_duty[t], 1e-6) + for x in self.feed_heater.control_volume.length_domain: + ssf(self.feed_heater.control_volume.enthalpy_flow_dx[t, x, "Vap"], 1e-7) + ssf(self.feed_heater.heat_holdup[t, x], 1e-9) + ssf(self.feed_heater.control_volume.heat[t, x], 1e-6) + ssf(self.feed_heater.control_volume._enthalpy_flow[t, x, "Vap"], 1e-8) + + ssf(self.sweep_heater.electric_heat_duty[t], 1e-6) + for x in self.sweep_heater.control_volume.length_domain: + ssf(self.sweep_heater.control_volume.heat[t, x], 1e-6) + ssf(self.sweep_heater.control_volume._enthalpy_flow[t, x, "Vap"], 1e-8) + ssf( + self.sweep_heater.control_volume.enthalpy_flow_dx[t, x, "Vap"], 1e-7 + ) + ssf(self.sweep_heater.heat_holdup[t, x], 1e-9) def scale_hx(hx): shell = hx.hot_side tube = hx.cold_side - ssf(shell.area, 1e-1) - ssf(hx.hot_side.heat, 1e-6) ssf(tube.area, 1) - ssf(hx.cold_side.heat, 1e-6) - ssf(shell._enthalpy_flow, 1e-8) - ssf(tube._enthalpy_flow, 1e-8) - ssf(shell.enthalpy_flow_dx, 1e-7) - ssf(tube.enthalpy_flow_dx, 1e-7) - ssf(hx.heat_holdup, 1e-8) + ssf(shell.area, 1e-1) + for t in hx.flowsheet().time: + for x in shell.length_domain: + ssf(hx.hot_side.heat[t, x], 1e-6) + ssf(hx.cold_side.heat[t, x], 1e-6) + ssf(shell._enthalpy_flow[t, x, "Vap"], 1e-8) + ssf(tube._enthalpy_flow[t, x, "Vap"], 1e-8) + ssf(shell.enthalpy_flow_dx[t, x, "Vap"], 1e-7) + ssf(tube.enthalpy_flow_dx[t, x, "Vap"], 1e-7) + ssf(hx.heat_holdup[t, x], 1e-8) scale_hx(self.sweep_exchanger) scale_hx(self.feed_medium_exchanger) @@ -954,6 +1013,9 @@ def fix_hx_params(hx): self.feed_hot_exchanger.number_columns_per_pass.fix(50) self.feed_hot_exchanger.number_rows_per_pass.fix(25) + if self.config.soc_heat_loss: + self.soc_module.total_heat_loss.fix(0) + def initialize_build( self, outlvl=idaeslog.NOTSET, @@ -1363,7 +1425,7 @@ def _add_tags(self): display_units=pyo.units.MW, ) tag_group["total_electric_power"] = iutil.ModelTag( - doc="Total electric power for SOEC and auxiliaries", + doc="Total electric power for SOC and auxiliaries", expr=self.total_electric_power[t0], format_string="{:.3f}", display_units=pyo.units.MW, @@ -1374,6 +1436,13 @@ def _add_tags(self): format_string="{:.1f}", display_units=pyo.units.dimensionless, ) + if self.config.soc_heat_loss: + tag_group["soc_heat_loss"] = iutil.ModelTag( + doc="SOC heat loss", + expr=self.soc_module.total_heat_loss[t0], + format_string="{:.1f}", + display_units=pyo.units.MW, + ) tag_group = iutil.ModelTagGroup() self.tags_input = tag_group @@ -1390,7 +1459,7 @@ def _stream_table(tag_group): rows = set() cols = set() tags = [] - for tag, stream, col in SoecStandaloneFlowsheetData._stream_col_gen(tag_group): + for tag, stream, col in SocStandaloneFlowsheetData._stream_col_gen(tag_group): rows.add(stream) cols.add(col) tags.append((tag, stream, col)) @@ -1455,41 +1524,48 @@ def add_controllers(self, variable_pairings): def _make_temperature_gradient_terms(self): soec = self.soc_module.solid_oxide_cell - dz = soec.zfaces.at(2) - soec.zfaces.at(1) - # Going to assume that the zfaces are evenly spaced - for iz in soec.iznodes: - assert abs(soec.zfaces.at(iz + 1) - soec.zfaces.at(iz) - dz) < 1e-8 - dz = dz * soec.length_z def finite_difference(expr, t, ix, iz): # Since this is mostly for reference, no need to worry about upwinding or whatever if iz == soec.iznodes.first(): + z0 = soec.znodes.at(iz) * soec.length_z + z1 = soec.znodes.at(iz + 1) * soec.length_z + z2 = soec.znodes.at(iz + 2) * soec.length_z + weights = [ + 1 / (z0 - z1) + 1 / (z0 - z2), + (z0 - z2) / ((z1 - z0) * (z1 - z2)), + (z0 - z1) / ((z2 - z0) * (z2 - z1)), + ] if ix is None: - return ( - -1.5 * expr[t, iz] + 2 * expr[t, iz + 1] - 0.5 * expr[t, iz + 2] - ) / dz + return sum(weights[i] * expr[t, iz + i] for i in range(3)) else: - return ( - -1.5 * expr[t, ix, iz] - + 2 * expr[t, ix, iz + 1] - - 0.5 * expr[t, ix, iz + 2] - ) / dz + return sum(weights[i] * expr[t, ix, iz + i] for i in range(3)) elif iz == soec.iznodes.last(): + z0 = soec.znodes.at(iz - 2) * soec.length_z + z1 = soec.znodes.at(iz - 1) * soec.length_z + z2 = soec.znodes.at(iz) * soec.length_z + weights = [ + (z2 - z1) / ((z0 - z1) * (z0 - z2)), + (z2 - z0) / ((z1 - z0) * (z1 - z2)), + 1 / (z2 - z0) + 1 / (z2 - z1), + ] if ix is None: - return ( - 1.5 * expr[t, iz] - 2 * expr[t, iz - 1] + 0.5 * expr[t, iz - 2] - ) / dz + return sum(weights[i] * expr[t, iz + i - 2] for i in range(3)) else: - return ( - 1.5 * expr[t, ix, iz] - - 2 * expr[t, ix, iz - 1] - + 0.5 * expr[t, ix, iz - 2] - ) / dz + return sum(weights[i] * expr[t, ix, iz + i - 2] for i in range(3)) else: + z0 = soec.znodes.at(iz - 1) * soec.length_z + z1 = soec.znodes.at(iz) * soec.length_z + z2 = soec.znodes.at(iz + 1) * soec.length_z + weights = [ + (z1 - z2) / ((z0 - z1) * (z0 - z2)), + 1 / (z1 - z2) + 1 / (z1 - z0), + (z1 - z0) / ((z2 - z0) * (z2 - z1)), + ] if ix is None: - return (0.5 * expr[t, iz + 1] - 0.5 * expr[t, iz - 1]) / dz + return sum(weights[i] * expr[t, iz + i - 1] for i in range(3)) else: - return (0.5 * expr[t, ix, iz + 1] - 0.5 * expr[t, ix, iz - 1]) / dz + return sum(weights[i] * expr[t, ix, iz + i - 1] for i in range(3)) soec.dtemperature_z_dz = pyo.Var( self.time, soec.iznodes, initialize=0, units=pyo.units.K / pyo.units.m @@ -1608,32 +1684,35 @@ def temperature_upper_bound_eqn(b, t, iz): delta_T_limit = 75 + z0 = self.soc_module.solid_oxide_cell.iznodes.first() + zend = self.soc_module.solid_oxide_cell.iznodes.last() + @self.Constraint(self.time) def thermal_gradient_eqn_1(b, t): return ( - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 1] - - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 10] + b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, z0] + - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, zend] ) <= delta_T_limit @self.Constraint(self.time) def thermal_gradient_eqn_2(b, t): return ( - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 10] - - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 1] + b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, zend] + - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, z0] ) <= delta_T_limit @self.Constraint(self.time) def thermal_gradient_eqn_3(b, t): return ( - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 1] - - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 10] + b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, z0] + - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, zend] ) >= -delta_T_limit @self.Constraint(self.time) def thermal_gradient_eqn_4(b, t): return ( - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 10] - - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, 1] + b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, zend] + - b.soc_module.solid_oxide_cell.fuel_electrode.temperature[t, 1, z0] ) >= -delta_T_limit iscale.constraint_scaling_transform(self.thermal_gradient_eqn_1[t0], 1e-2) diff --git a/idaes_examples/notebooks/docs/power_gen/solid_oxide_cell/max_production.json.gz b/idaes_examples/notebooks/docs/power_gen/solid_oxide_cell/max_production.json.gz index 52aae2e635c04f8c70f2e2dd9b0c4c67b3a8ca04..b5c27c4863d3ff8e49207527a420cd247281e001 100644 GIT binary patch literal 213722 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
" ] }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.029237Z", - "start_time": "2025-07-15T22:29:19.021824Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.117688Z", - "start_time": "2025-07-15T22:29:19.037801Z" + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" } }, "cell_type": "code", @@ -321,7 +300,7 @@ "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" ], "outputs": [], - "execution_count": 9 + "execution_count": 8 }, { "cell_type": "markdown", @@ -336,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.131934Z", - "start_time": "2025-07-15T22:29:19.127335Z" + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" } }, "source": [ @@ -345,7 +324,7 @@ "m.fs = FlowsheetBlock(dynamic=False)" ], "outputs": [], - "execution_count": 10 + "execution_count": 9 }, { "cell_type": "markdown", @@ -358,68 +337,18 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:20.186702Z", - "start_time": "2025-07-15T22:29:19.143102Z" + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" } }, "source": [ - "# m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - "# property_package=m.fs.thermo_params\n", - "# )\n", - "\n", "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", - "# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "2025-07-15 16:29:19 [ERROR] idaes.core.base.process_block: Failure in build: fs.thermo_params\n", - "Traceback (most recent call last):\n", - " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py\", line 41, in _rule_default\n", - " b.build()\n", - " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py\", line 470, in build\n", - " for p in self.phase_list:\n", - " ^^^^^^^^^^^^^^^\n", - " File \"C:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py\", line 550, in __getattr__\n", - " raise AttributeError(\n", - "AttributeError: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'\n", - "ERROR: Constructing component 'fs.thermo_params' from data=None failed:\n", - " AttributeError: '_ScalarGenericParameterBlock' object has no attribute\n", - " 'phase_list'\n" - ] - }, - { - "ename": "AttributeError", - "evalue": "'_ScalarGenericParameterBlock' object has no attribute 'phase_list'", - "output_type": "error", - "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[11]\u001B[39m\u001B[32m, line 6\u001B[39m\n\u001B[32m 1\u001B[39m \u001B[38;5;66;03m# m.fs.thermo_params = thermo_props.HDAParameterBlock()\u001B[39;00m\n\u001B[32m 2\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\u001B[39;00m\n\u001B[32m 3\u001B[39m \u001B[38;5;66;03m# property_package=m.fs.thermo_params\u001B[39;00m\n\u001B[32m 4\u001B[39m \u001B[38;5;66;03m# )\u001B[39;00m\n\u001B[32m----> \u001B[39m\u001B[32m6\u001B[39m \u001B[43mm\u001B[49m\u001B[43m.\u001B[49m\u001B[43mfs\u001B[49m\u001B[43m.\u001B[49m\u001B[43mthermo_params\u001B[49m = GenericParameterBlock(**thermo_config)\n\u001B[32m 7\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)\u001B[39;00m\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:571\u001B[39m, in \u001B[36mBlockData.__setattr__\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 566\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m name \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m.\u001B[34m__dict__\u001B[39m:\n\u001B[32m 567\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(val, Component):\n\u001B[32m 568\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 569\u001B[39m \u001B[38;5;66;03m# Pyomo components are added with the add_component method.\u001B[39;00m\n\u001B[32m 570\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m571\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43madd_component\u001B[49m\u001B[43m(\u001B[49m\u001B[43mname\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mval\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 572\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 573\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 574\u001B[39m \u001B[38;5;66;03m# Other Python objects are added with the standard __setattr__\u001B[39;00m\n\u001B[32m 575\u001B[39m \u001B[38;5;66;03m# method.\u001B[39;00m\n\u001B[32m 576\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 577\u001B[39m \u001B[38;5;28msuper\u001B[39m(BlockData, \u001B[38;5;28mself\u001B[39m).\u001B[34m__setattr__\u001B[39m(name, val)\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:1101\u001B[39m, in \u001B[36mBlockData.add_component\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 1093\u001B[39m logger.debug(\n\u001B[32m 1094\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mConstructing \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m on \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m from data=\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m\"\u001B[39m,\n\u001B[32m 1095\u001B[39m val.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m,\n\u001B[32m (...)\u001B[39m\u001B[32m 1098\u001B[39m \u001B[38;5;28mstr\u001B[39m(data),\n\u001B[32m 1099\u001B[39m )\n\u001B[32m 1100\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1101\u001B[39m \u001B[43mval\u001B[49m\u001B[43m.\u001B[49m\u001B[43mconstruct\u001B[49m\u001B[43m(\u001B[49m\u001B[43mdata\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1102\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m:\n\u001B[32m 1103\u001B[39m err = sys.exc_info()[\u001B[32m1\u001B[39m]\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2233\u001B[39m, in \u001B[36mBlock.construct\u001B[39m\u001B[34m(self, data)\u001B[39m\n\u001B[32m 2231\u001B[39m obj.construct(data.get(name, \u001B[38;5;28;01mNone\u001B[39;00m))\n\u001B[32m 2232\u001B[39m \u001B[38;5;66;03m# Trigger the (normal) initialization of the block\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m2233\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_getitem_when_not_present\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_idx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2234\u001B[39m \u001B[38;5;28;01mfinally\u001B[39;00m:\n\u001B[32m 2235\u001B[39m \u001B[38;5;66;03m# We must allow that id(self) may no longer be in\u001B[39;00m\n\u001B[32m 2236\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data, as _getitem_when_not_present will\u001B[39;00m\n\u001B[32m 2237\u001B[39m \u001B[38;5;66;03m# have already removed the entry for scalar blocks (as the\u001B[39;00m\n\u001B[32m 2238\u001B[39m \u001B[38;5;66;03m# BlockData and the Block component are the same object)\u001B[39;00m\n\u001B[32m 2239\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m data \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2148\u001B[39m, in \u001B[36mBlock._getitem_when_not_present\u001B[39m\u001B[34m(self, idx)\u001B[39m\n\u001B[32m 2145\u001B[39m data = \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[32m 2147\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m2148\u001B[39m obj = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_rule\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_block\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2149\u001B[39m \u001B[38;5;66;03m# If the user returns a block, transfer over everything\u001B[39;00m\n\u001B[32m 2150\u001B[39m \u001B[38;5;66;03m# they defined into the empty one we created. We do\u001B[39;00m\n\u001B[32m 2151\u001B[39m \u001B[38;5;66;03m# this inside the try block so that any abstract\u001B[39;00m\n\u001B[32m 2152\u001B[39m \u001B[38;5;66;03m# components declared by the rule have the opportunity\u001B[39;00m\n\u001B[32m 2153\u001B[39m \u001B[38;5;66;03m# to be initialized with data from\u001B[39;00m\n\u001B[32m 2154\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data as they are transferred over.\u001B[39;00m\n\u001B[32m 2155\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m obj \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m _block \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(obj, BlockData):\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\initializer.py:351\u001B[39m, in \u001B[36mIndexedCallInitializer.__call__\u001B[39m\u001B[34m(self, parent, idx)\u001B[39m\n\u001B[32m 349\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m._fcn(parent, *idx)\n\u001B[32m 350\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m--> \u001B[39m\u001B[32m351\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_fcn\u001B[49m\u001B[43m(\u001B[49m\u001B[43mparent\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n", - "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py:41\u001B[39m, in \u001B[36m_rule_default\u001B[39m\u001B[34m(b, *args)\u001B[39m\n\u001B[32m 35\u001B[39m \u001B[38;5;250m\u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 36\u001B[39m \u001B[33;03mDefault rule for ProcessBlock, which calls build(). A different rule can\u001B[39;00m\n\u001B[32m 37\u001B[39m \u001B[33;03mbe specified to add additional build steps, or to not call build at all\u001B[39;00m\n\u001B[32m 38\u001B[39m \u001B[33;03musing the normal rule argument to ProcessBlock init.\u001B[39;00m\n\u001B[32m 39\u001B[39m \u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 40\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m---> \u001B[39m\u001B[32m41\u001B[39m \u001B[43mb\u001B[49m\u001B[43m.\u001B[49m\u001B[43mbuild\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 42\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m:\n\u001B[32m 43\u001B[39m logging.getLogger(\u001B[34m__name__\u001B[39m).exception(\u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33mFailure in build: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mb\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m\"\u001B[39m)\n", - "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py:470\u001B[39m, in \u001B[36mGenericParameterData.build\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 468\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m._electrolyte:\n\u001B[32m 469\u001B[39m pc_set = []\n\u001B[32m--> \u001B[39m\u001B[32m470\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mphase_list\u001B[49m:\n\u001B[32m 471\u001B[39m pobj = \u001B[38;5;28mself\u001B[39m.get_phase(p)\n\u001B[32m 472\u001B[39m pc_list = \u001B[38;5;28mself\u001B[39m.get_phase(p).config.component_list\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:550\u001B[39m, in \u001B[36mBlockData.__getattr__\u001B[39m\u001B[34m(self, val)\u001B[39m\n\u001B[32m 547\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m _component_decorator(\u001B[38;5;28mself\u001B[39m, ModelComponentFactory.get_class(val))\n\u001B[32m 548\u001B[39m \u001B[38;5;66;03m# Since the base classes don't support getattr, we can just\u001B[39;00m\n\u001B[32m 549\u001B[39m \u001B[38;5;66;03m# throw the \"normal\" AttributeError\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m550\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mAttributeError\u001B[39;00m(\n\u001B[32m 551\u001B[39m \u001B[33m\"\u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m object has no attribute \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m\"\u001B[39m % (\u001B[38;5;28mself\u001B[39m.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m, val)\n\u001B[32m 552\u001B[39m )\n", - "\u001B[31mAttributeError\u001B[39m: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'" - ] - } + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" ], - "execution_count": 11 + "outputs": [], + "execution_count": 10 }, { "cell_type": "markdown", @@ -432,7 +361,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, "source": [ "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", @@ -450,7 +384,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 11 }, { "cell_type": "markdown", @@ -478,20 +412,28 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } }, "source": [ "# Todo: Add reactor with the specifications above" ], "outputs": [], - "execution_count": null + "execution_count": 12 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } }, "source": [ "# Todo: Add reactor with the specifications above\n", @@ -504,7 +446,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 13 }, { "cell_type": "markdown", @@ -520,7 +462,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", @@ -529,7 +476,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 14 }, { "cell_type": "markdown", @@ -540,7 +487,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -562,7 +514,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 15 }, { "cell_type": "markdown", @@ -573,7 +525,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -582,7 +539,7 @@ "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], - "execution_count": null + "execution_count": 16 }, { "cell_type": "markdown", @@ -602,14 +559,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 17 }, { "cell_type": "markdown", @@ -630,27 +592,35 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet" ], "outputs": [], - "execution_count": null + "execution_count": 18 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 19 }, { "cell_type": "markdown", @@ -661,7 +631,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", @@ -670,7 +645,7 @@ "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], - "execution_count": null + "execution_count": 20 }, { "cell_type": "markdown", @@ -681,14 +656,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 21 }, { "cell_type": "markdown", @@ -699,12 +679,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" ], "outputs": [], - "execution_count": null + "execution_count": 22 }, { "cell_type": "markdown", @@ -726,18 +711,27 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, "source": [ "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", " )\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 23 }, { "cell_type": "markdown", @@ -748,14 +742,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 24 }, { "cell_type": "markdown", @@ -772,14 +771,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 25 }, { "cell_type": "markdown", @@ -790,39 +794,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" ], "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": {}, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [], - "execution_count": null + "execution_count": 26 }, { "cell_type": "markdown", @@ -836,26 +820,43 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.409008Z", + "start_time": "2025-11-20T21:46:10.382157Z" + } }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" ], "outputs": [], - "execution_count": null + "execution_count": 28 }, { "cell_type": "markdown", @@ -866,21 +867,32 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", "m.fs.I101.temperature.fix(303.2)\n", "m.fs.I101.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 29 }, { "cell_type": "markdown", @@ -900,21 +912,36 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", "m.fs.I102.temperature.fix(303.2)\n", "m.fs.I102.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 30 }, { "cell_type": "markdown", @@ -927,12 +954,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.fix(600)" ], "outputs": [], - "execution_count": null + "execution_count": 31 }, { "cell_type": "markdown", @@ -943,15 +975,23 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", " )\n", ")\n", "\n", @@ -959,7 +999,7 @@ "m.fs.R101.heat_duty.fix(0)" ], "outputs": [], - "execution_count": null + "execution_count": 32 }, { "cell_type": "markdown", @@ -970,13 +1010,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" ], "outputs": [], - "execution_count": null + "execution_count": 33 }, { "cell_type": "markdown", @@ -1003,27 +1048,35 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } }, "source": [ "# Todo: Set conditions for Flash F102" ], "outputs": [], - "execution_count": null + "execution_count": 34 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } }, "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" ], "outputs": [], - "execution_count": null + "execution_count": 35 }, { "cell_type": "markdown", @@ -1034,13 +1087,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 36 }, { "cell_type": "markdown", @@ -1063,51 +1121,60 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } }, "source": [ "# Todo: print the degrees of freedom" ], "outputs": [], - "execution_count": null + "execution_count": 37 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.568992Z", + "start_time": "2025-11-20T21:46:10.542995Z" + } }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ], "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ] - }, - "source": [], - "outputs": [], - "execution_count": null + "execution_count": 39 }, { "cell_type": "markdown", @@ -1140,7 +1207,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -1153,7 +1225,7 @@ "order = seq.calculation_order(G)" ], "outputs": [], - "execution_count": null + "execution_count": 40 }, { "cell_type": "markdown", @@ -1164,13 +1236,26 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 }, { "cell_type": "markdown", @@ -1182,14 +1267,31 @@ { "cell_type": "code", "metadata": { - "scrolled": true + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } }, "source": [ "for o in order:\n", " print(o[0].name)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 }, { "cell_type": "markdown", @@ -1205,18 +1307,25 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, "source": [ "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1226,7 +1335,7 @@ "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" ], "outputs": [], - "execution_count": null + "execution_count": 43 }, { "cell_type": "markdown", @@ -1237,7 +1346,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, "source": [ "def function(unit):\n", " try:\n", @@ -1248,7 +1362,7 @@ " solver.solve(unit)" ], "outputs": [], - "execution_count": null + "execution_count": 44 }, { "cell_type": "markdown", @@ -1259,12 +1373,567 @@ }, { "cell_type": "code", - "metadata": {}, - "source": [ - "# seq.run(m, function)" + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } ], - "outputs": [], - "execution_count": null + "execution_count": 45 }, { "cell_type": "markdown", @@ -1278,12 +1947,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, "source": [ "from idaes.core.util.initialization import propagate_state" ], "outputs": [], - "execution_count": null + "execution_count": 46 }, { "cell_type": "markdown", @@ -1296,12 +1970,15 @@ }, { "cell_type": "code", - "metadata": {}, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", "outputs": [], - "execution_count": null + "execution_count": 47 }, { "cell_type": "markdown", @@ -1312,14 +1989,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" ], "outputs": [], - "execution_count": null + "execution_count": 48 }, { "cell_type": "markdown", @@ -1330,32 +2012,40 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" ], "outputs": [], - "execution_count": null + "execution_count": 49 }, { "cell_type": "markdown", @@ -1366,38 +2056,45 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [], - "execution_count": null + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 }, { "cell_type": "markdown", @@ -1408,7 +2105,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1416,11 +2118,92 @@ " \"max_iter\": 300,\n", " \"tol\": 1e-8,\n", "}\n", - "solver = get_solver(options=optarg)\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 }, { "cell_type": "markdown", @@ -1431,7 +2214,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1442,8 +2230,16 @@ " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", ")" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 }, { "cell_type": "markdown", @@ -1463,7 +2259,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1473,7 +2274,7 @@ "}" ], "outputs": [], - "execution_count": null + "execution_count": 53 }, { "cell_type": "markdown", @@ -1499,7 +2300,11 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } }, "source": [ "# Create the solver object\n", @@ -1507,31 +2312,118 @@ "# Solve the model" ], "outputs": [], - "execution_count": null + "execution_count": 54 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } }, "source": [ "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", "\n", "# Solve the model\n", "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.393870Z", + "start_time": "2025-11-20T21:46:17.390132Z" + } }, "source": [ "# Check solver solve status\n", @@ -1540,7 +2432,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": null + "execution_count": 56 }, { "cell_type": "markdown", @@ -1563,13 +2455,17 @@ "metadata": { "tags": [ "noauto" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } }, "source": [ "# m.fs.visualize(\"HDA-Flowsheet\")" ], "outputs": [], - "execution_count": null + "execution_count": 57 }, { "cell_type": "markdown", @@ -1580,12 +2476,38 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, "source": [ "m.fs.report()" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 }, { "cell_type": "markdown", @@ -1596,27 +2518,44 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.571498Z", + "start_time": "2025-11-20T21:46:17.493194Z" + } }, "source": [ "import pytest\n", "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" + "assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 60 }, { "cell_type": "markdown", @@ -1627,30 +2566,81 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.619054Z", + "start_time": "2025-11-20T21:46:17.613393Z" + } }, "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 62 }, { "cell_type": "markdown", @@ -1661,7 +2651,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -1671,8 +2666,23 @@ "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 }, { "cell_type": "markdown", @@ -1705,12 +2715,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" ], "outputs": [], - "execution_count": null + "execution_count": 64 }, { "cell_type": "markdown", @@ -1721,7 +2736,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", @@ -1729,7 +2749,7 @@ "m.fs.F102.vap_outlet.temperature.unfix()" ], "outputs": [], - "execution_count": null + "execution_count": 65 }, { "cell_type": "markdown", @@ -1753,40 +2773,52 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } }, "source": [ "# Todo: Unfix deltaP for F102" ], "outputs": [], - "execution_count": null + "execution_count": 66 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } }, "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" ], "outputs": [], - "execution_count": null + "execution_count": 67 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.759351Z", + "start_time": "2025-11-20T21:46:17.728327Z" + } }, "source": [ "assert degrees_of_freedom(m) == 5" ], "outputs": [], - "execution_count": null + "execution_count": 68 }, { "cell_type": "markdown", @@ -1805,13 +2837,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" ], "outputs": [], - "execution_count": null + "execution_count": 69 }, { "cell_type": "markdown", @@ -1834,20 +2871,28 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } }, "source": [ "# Todo: Set the bounds for reactor outlet temperature" ], "outputs": [], - "execution_count": null + "execution_count": 70 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } }, "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", @@ -1855,7 +2900,7 @@ "m.fs.R101.outlet.temperature[0].setub(800)" ], "outputs": [], - "execution_count": null + "execution_count": 71 }, { "cell_type": "markdown", @@ -1866,7 +2911,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -1876,7 +2926,7 @@ "m.fs.F102.vap_outlet.pressure[0].setub(110000)" ], "outputs": [], - "execution_count": null + "execution_count": 72 }, { "cell_type": "markdown", @@ -1887,15 +2937,23 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, "source": [ "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 73 }, { "cell_type": "markdown", @@ -1918,29 +2976,40 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } }, "source": [ "# Todo: Add minimum product flow constraint" ], "outputs": [], - "execution_count": null + "execution_count": 74 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } }, "source": [ "# Todo: Add minimum product flow constraint\n", "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 75 }, { "cell_type": "markdown", @@ -1951,12 +3020,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" ], "outputs": [], - "execution_count": null + "execution_count": 76 }, { "cell_type": "markdown", @@ -1970,19 +3044,134 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, "source": [ "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.045752Z", + "start_time": "2025-11-20T21:46:18.041549Z" + } }, "source": [ "# Check for solver solve status\n", @@ -1991,7 +3180,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": null + "execution_count": 78 }, { "cell_type": "markdown", @@ -2004,7 +3193,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -2020,22 +3214,106 @@ "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.093619Z", + "start_time": "2025-11-20T21:46:18.090039Z" + } }, "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", + "assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 80 }, { "cell_type": "markdown", @@ -2046,7 +3324,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, "source": [ "print(\n", " f\"\"\"Optimal Values:\n", @@ -2062,25 +3345,67 @@ "\"\"\"\n", ")" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:19.262061Z", + "start_time": "2025-11-20T21:46:18.121920Z" + } }, "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", + "print(value(m.fs.R101.outlet.temperature[0]))\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "763.5072359720118\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAssertionError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[82]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.H101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m500\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m763.484\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F101.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m301.881\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 5\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F102.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m362.935\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n", + "\u001b[31mAssertionError\u001b[39m: " + ] + } + ], + "execution_count": 82 } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py index 39b56e2f..57eac3e4 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py @@ -1,11 +1,9 @@ - from pyomo.environ import ( Constraint, Var, ConcreteModel, Expression, Objective, - SolverFactory, TransformationFactory, value, ) @@ -15,35 +13,26 @@ from idaes.models.unit_models import ( PressureChanger, - IsentropicPressureChangerInitializer, Mixer, - MixerInitializer, Separator as Splitter, - SeparatorInitializer, Heater, StoichiometricReactor, Feed, Product, ) +from idaes.core.util.exceptions import InitializationError +import idaes.logger as idaeslog + # Todo: import flash model from idaes.models.unit_models # Todo: import flash model from idaes.models.unit_models from idaes.models.unit_models import Flash - from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption from idaes.core.util.model_statistics import degrees_of_freedom -from idaes.core.scaling.util import set_scaling_factor -from idaes.core.scaling.autoscaling import AutoScaler - -import idaes.logger as idaeslog from idaes.core.solvers import get_solver -from idaes.core.util.exceptions import InitializationError - -from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props -from idaes_examples.mod.hda import hda_reaction as reaction_props from idaes.models.properties.modular_properties.base.generic_property import ( GenericParameterBlock, @@ -54,22 +43,15 @@ from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config from idaes_examples.mod.hda.hda_reaction_modular import reaction_config - m = ConcreteModel() m.fs = FlowsheetBlock(dynamic=False) -thermo_params_og = thermo_props.HDAParameterBlock() -reaction_params_og = reaction_props.HDAReactionParameterBlock(property_package=thermo_params_og) -thermo_params_new = GenericParameterBlock(**thermo_config) -reaction_params_new = GenericReactionParameterBlock(property_package=thermo_params_new, **reaction_config) - -# m.fs.thermo_params = thermo_params_og -# m.fs.reaction_params = reaction_params_og -m.fs.thermo_params = thermo_params_new -m.fs.reaction_params = reaction_params_new +m.fs.thermo_params = GenericParameterBlock(**thermo_config) +m.fs.reaction_params = GenericReactionParameterBlock( + property_package=m.fs.thermo_params, **reaction_config +) m.fs.I101 = Feed(property_package=m.fs.thermo_params) - m.fs.I102 = Feed(property_package=m.fs.thermo_params) m.fs.M101 = Mixer( @@ -103,7 +85,6 @@ outlet_list=["purge", "recycle"], ) - m.fs.C101 = PressureChanger( property_package=m.fs.thermo_params, compressor=True, @@ -136,10 +117,14 @@ TransformationFactory("network.expand_arcs").apply_to(m) m.fs.purity = Expression( - expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] / ( - m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] - + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "toluene"] + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] + + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "toluene" + ] ) ) @@ -155,32 +140,43 @@ expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) ) -# autoscaler = AutoScaler() -# autoscaler.scale_model(m) +assert degrees_of_freedom(m) == 29 -print(degrees_of_freedom(m)) +F_liq_toluene = 0.30 +F_liq_non_zero = 1e-5 -assert degrees_of_freedom(m) == 29 +F_vap_I101 = F_liq_non_zero * 4 +F_liq_I101 = F_liq_toluene + F_liq_non_zero -m.fs.I101.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "methane"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "toluene"].fix(0.30) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I101.flow_mol_phase[0, "Vap"].fix(F_vap_I101) +m.fs.I101.flow_mol_phase[0, "Liq"].fix(F_liq_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I101) +m.fs.I101.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_toluene / F_liq_I101) m.fs.I101.temperature.fix(303.2) m.fs.I101.pressure.fix(350000) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(0.30) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "methane"].fix(0.02) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "toluene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +F_vap_hydrogen = 0.30 +F_vap_methane = 0.020 + +F_vap_non_zero = 1e-5 +F_liq_non_zero = F_vap_non_zero + +F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero +F_liq_I102 = 2 * F_vap_non_zero + +m.fs.I102.flow_mol_phase[0, "Vap"].fix(F_vap_I102) +m.fs.I102.flow_mol_phase[0, "Liq"].fix(F_liq_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_vap_non_zero / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_vap_non_zero / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_vap_hydrogen / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_vap_methane / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I102) +m.fs.I102.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_non_zero / F_liq_I102) + m.fs.I102.temperature.fix(303.2) m.fs.I102.pressure.fix(350000) @@ -189,8 +185,15 @@ m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) m.fs.R101.conv_constraint = Constraint( - expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - == (m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) + expr=m.fs.R101.conversion + * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"]) + == ( + m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"] + - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "toluene" + ] + ) +) m.fs.R101.conversion.fix(0.75) m.fs.R101.heat_duty.fix(0) @@ -204,93 +207,107 @@ m.fs.S101.split_fraction[0, "purge"].fix(0.2) m.fs.C101.outlet.pressure.fix(350000) -from idaes.core.util.initialization import propagate_state +seq = SequentialDecomposition() +seq.options.select_tear_method = "heuristic" +seq.options.tear_method = "Wegstein" +seq.options.iterLim = 3 + +# Using the SD tool +G = seq.create_graph(m) +heuristic_tear_set = seq.tear_set_arcs(G, method="heuristic") +order = seq.calculation_order(G) + +for o in heuristic_tear_set: + print(o.name) + +for o in order: + print(o[0].name) -print(f"The DOF is {degrees_of_freedom(m)} initially") -m.fs.s03_expanded.deactivate() -print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") tear_guesses = { - "flow_mol_phase_comp": { - (0, "Liq", "benzene"): 1e-5, - (0, "Liq", "toluene"): 0.30, - (0, "Liq", "methane"): 1e-5, - (0, "Liq", "hydrogen"): 1e-5, - (0, "Vap", "benzene"): 1e-5, - (0, "Vap", "toluene"): 1e-5, - (0, "Vap", "methane"): 0.5, - (0, "Vap", "hydrogen"): 0.5, + "flow_mol_phase": { + (0, "Liq"): F_liq_I101, + (0, "Vap"): F_vap_I102, + }, + "mole_frac_phase_comp": { + (0, "Liq", "benzene"): 1e-5 / F_liq_I101, + (0, "Liq", "toluene"): 0.30 / F_liq_I101, + (0, "Vap", "benzene"): 1e-5 / F_vap_I102, + (0, "Vap", "toluene"): 1e-5 / F_vap_I102, + (0, "Vap", "methane"): 0.02 / F_vap_I102, + (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, }, "temperature": {0: 303}, "pressure": {0: 350000}, } -for k, v in tear_guesses.items(): - for k1, v1 in v.items(): - getattr(m.fs.s03.destination, k)[k1].fix(v1) - -DOF_initial = degrees_of_freedom(m) -# x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) -# x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) -# x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) -# x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) - -# p_sat_dewT_0 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['benzene']) -# p_sat_dewT_1 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['toluene']) -# p_sat_dewT_2 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['hydrogen']) -# p_sat_dewT_3 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['methane']) -# -# print(p_sat_dewT_0) -# print(p_sat_dewT_1) -# print(p_sat_dewT_2) -# print(p_sat_dewT_3) +# Pass the tear_guess to the SD tool +seq.set_guesses_for(m.fs.H101.inlet, tear_guesses) + + +def function(unit): + try: + initializer = unit.default_initializer() + initializer.initialize(unit, output_level=idaeslog.INFO) + except InitializationError: + solver = get_solver() + solver.solve(unit) +seq.run(m, function) + +# from idaes.core.util.initialization import propagate_state # -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['benzene'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['toluene'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['hydrogen'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['methane'])) +# print(f"The DOF is {degrees_of_freedom(m)} initially") +# m.fs.s03_expanded.deactivate() +# print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") # -# print(value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew['Vap', 'Liq'])) - -# P = value(m.fs.H101.control_volume.properties_out[0.0].pressure) +# tear_guesses = { +# "flow_mol_phase": { +# (0, "Liq"): F_liq_I101, +# (0, "Vap"): F_vap_I102, # -# print(P*(x_0/p_sat_dewT_0 + x_1/p_sat_dewT_1) - 1) - - -m.fs.H101.default_initializer().initialize(m.fs.H101, output_level=idaeslog.INFO_HIGH) # Initialize Heater -x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) -x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) -x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) -x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) - -T_dew = value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew) -T_bub = value(m.fs.H101.control_volume.properties_out[0.0].temperature_bubble) -P_dew = value(m.fs.H101.control_volume.properties_out[0.0].pressure_dew) -P_bub = value(m.fs.H101.control_volume.properties_out[0.0].pressure_bubble) - -m.fs.H101.default_initializer().initialize(m.fs.H101) -propagate_state(m.fs.s04) # Establish connection between Heater and Reactor -m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor -propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit -m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit -propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter -propagate_state(m.fs.s07) -m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter -propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor -m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor -propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer -m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet -propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer -m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet -propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer -m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer -propagate_state(m.fs.s03) # Establish connection between Mixer and Heater -m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit -propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product -propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product -propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product - +# }, +# "mole_frac_phase_comp": { +# (0, "Liq", "benzene"): 1e-5 / F_liq_I101, +# (0, "Liq", "toluene"): 0.30 / F_liq_I101, +# (0, "Vap", "benzene"): 1e-5 / F_vap_I102, +# (0, "Vap", "toluene"): 1e-5 / F_vap_I102, +# (0, "Vap", "methane"): 0.02 / F_vap_I102, +# (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, +# }, +# "temperature": {0: 303}, +# "pressure": {0: 350000}, +# } +# +# for k, v in tear_guesses.items(): +# for k1, v1 in v.items(): +# getattr(m.fs.s03.destination, k)[k1].fix(v1) +# +# DOF_initial = degrees_of_freedom(m) +# +# print(f"The DOF is {degrees_of_freedom(m)} after setting the tear stream") +# +# m.fs.H101.default_initializer().initialize(m.fs.H101) +# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor +# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor +# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit +# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit +# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter +# propagate_state(m.fs.s07) +# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter +# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor +# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor +# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer +# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet +# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer +# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet +# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer +# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer +# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater +# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit +# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product +# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product +# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product optarg = { "nlp_scaling_method": "user-scaling", @@ -298,10 +315,9 @@ "max_iter": 300, "tol": 1e-8, } -solver = get_solver(options=optarg) +solver = get_solver("ipopt_v2", options=optarg) results = solver.solve(m, tee=True) - for k, v in tear_guesses.items(): for k1, v1 in v.items(): getattr(m.fs.H101.inlet, k)[k1].unfix() @@ -310,79 +326,81 @@ print( f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" ) -#%% md +# %% md # ## 6 Solving the Model -#%% md +# %% md # We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html -#%% +# %% optarg = { "nlp_scaling_method": "user-scaling", "OF_ma57_automatic_scaling": "yes", "max_iter": 1000, "tol": 1e-8, } -#%% md +# %% md #
# Inline Exercise: # Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following: -# +# # solver = get_solver(solver_options=optarg)
# results = solver.solve(m, tee=True) -# +# # Use Shift+Enter to run the cell once you have typed in your code. #
-# -#%% +# +# %% # Create the solver object # Solve the model -#%% +# %% # Create the solver object -solver = get_solver(solver_options=optarg) +solver = get_solver("ipopt_v2", options=optarg) # Solve the model -results = solver.solve(m, tee=True) -#%% +results = solver.solve(m, tee=False) + +print(f"Solver result: {results}") +# %% # Check solver solve status from pyomo.environ import TerminationCondition assert results.solver.termination_condition == TerminationCondition.optimal -#%% md +# %% md # ## 7 Analyze the results -# -# -# -#%% md +# +# +# +# %% md # If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window. -# -#%% +# +# %% # m.fs.visualize("HDA-Flowsheet") -#%% md +# %% md # Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display. -#%% +# %% m.fs.report() -#%% md +# %% md # What is the total operating cost? -#%% +# %% print("operating cost = $", value(m.fs.operating_cost)) -#%% +# %% import pytest -assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3) -#%% md +# assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3) +# %% md # For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method. -#%% +# %% m.fs.F102.report() print() print("benzene purity = ", value(m.fs.purity)) -#%% +# %% assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) -assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3) +assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3) assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) -#%% md +# %% md # Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101. -#%% +# %% from idaes.core.util.tables import ( create_stream_table_dataframe, stream_table_dataframe_to_string, @@ -390,129 +408,135 @@ st = create_stream_table_dataframe({"Reactor": m.fs.s05, "Light Gases": m.fs.s06}) print(stream_table_dataframe_to_string(st)) -#%% md +# %% md # ## 8 Optimization -# -# -# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. -# +# +# +# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. +# # Let us try to minimize this cost such that: # - we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream # - purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80% # - restricting the benzene loss in F101 vapor outlet to less than 20% -# +# # For this problem, our decision variables are as follows: # - H101 outlet temperature # - R101 cooling duty provided # - F101 outlet temperature # - F102 outlet temperature # - F102 deltaP in the flash tank -# -#%% md -# Let us declare our objective function for this problem. -#%% +# +# %% md +# Let us declare our objective function for this problem. +# %% m.fs.objective = Objective(expr=m.fs.operating_cost) -#%% md -# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. -#%% +# %% md +# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. +# %% m.fs.H101.outlet.temperature.unfix() m.fs.R101.heat_duty.unfix() m.fs.F101.vap_outlet.temperature.unfix() m.fs.F102.vap_outlet.temperature.unfix() -#%% md +# %% md #
# Inline Exercise: -# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) -# -# Use Shift+Enter to run the cell once you have typed in your code. +# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-# -# -#%% +# +# +# %% # Todo: Unfix deltaP for F102 -#%% +# %% # Todo: Unfix deltaP for F102 m.fs.F102.deltaP.unfix() -#%% +# %% assert degrees_of_freedom(m) == 5 -#%% md +# %% md # Next, we need to set bounds on these decision variables to values shown below: -# +# # - H101 outlet temperature [500, 600] K # - R101 outlet temperature [600, 800] K # - F101 outlet temperature [298, 450] K # - F102 outlet temperature [298, 450] K # - F102 outlet pressure [105000, 110000] Pa -# +# # Let us first set the variable bound for the H101 outlet temperature as shown below: -#%% +# %% m.fs.H101.outlet.temperature[0].setlb(500) m.fs.H101.outlet.temperature[0].setub(600) -#%% md +# %% md #
# Inline Exercise: # Now, set the variable bound for the R101 outlet temperature. -# -# Use Shift+Enter to run the cell once you have typed in your code. +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-#%% +# %% # Todo: Set the bounds for reactor outlet temperature -#%% +# %% # Todo: Set the bounds for reactor outlet temperature m.fs.R101.outlet.temperature[0].setlb(600) m.fs.R101.outlet.temperature[0].setub(800) -#%% md -# Let us fix the bounds for the rest of the decision variables. -#%% +# %% md +# Let us fix the bounds for the rest of the decision variables. +# %% m.fs.F101.vap_outlet.temperature[0].setlb(298.0) m.fs.F101.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.temperature[0].setlb(298.0) m.fs.F102.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.pressure[0].setlb(105000) m.fs.F102.vap_outlet.pressure[0].setub(110000) -#%% md -# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. -#%% +# %% md +# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. +# %% m.fs.overhead_loss = Constraint( - expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] - <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + <= 0.20 + * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] ) -#%% md +# %% md #
# Inline Exercise: -# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. -# -# Use Shift+Enter to run the cell once you have typed in your code. +# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-#%% +# %% # Todo: Add minimum product flow constraint -#%% +# %% # Todo: Add minimum product flow constraint m.fs.product_flow = Constraint( - expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] >= 0.15 + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + >= 0.15 ) -#%% md -# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. -#%% +# %% md +# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. +# %% m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) -#%% md -# -# We have now defined the optimization problem and we are now ready to solve this problem. -# -# -# -#%% +# %% md +# +# We have now defined the optimization problem and we are now ready to solve this problem. +# +# +# +# %% results = solver.solve(m, tee=True) -#%% +# %% # Check for solver solve status from pyomo.environ import TerminationCondition assert results.solver.termination_condition == TerminationCondition.optimal -#%% md +# %% md # ### 8.1 Optimization Results -# +# # Display the results and product specifications -#%% +# %% print("operating cost = $", value(m.fs.operating_cost)) print() @@ -526,12 +550,13 @@ print() print("Overhead loss in F101") m.fs.F101.report() -#%% -assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3) +# %% + +assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3) assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) -#%% md +# %% md # Display optimal values for the decision variables -#%% +# %% print( f"""Optimal Values: @@ -545,9 +570,10 @@ F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa """ ) -#%% +# %% assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) -assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) -assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3) +# assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) +assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3) +assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3) assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) -assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) \ No newline at end of file +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 219269e0..22c9fbaa 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1,2543 +1,5016 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + }, + "tags": [ + "header", + "hide-cell" + ] + }, + "outputs": [], + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "outputs": [], + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "outputs": [], + "source": [ + "from idaes.core import FlowsheetBlock" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "outputs": [], + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "outputs": [], + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "outputs": [], + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "outputs": [], + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "outputs": [], + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "outputs": [], + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "outputs": [], + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "outputs": [], + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "outputs": [], + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "outputs": [], + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "source": [ + "print(degrees_of_freedom(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "outputs": [], + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "outputs": [], + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "outputs": [], + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "outputs": [], + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "source": [ + "print(degrees_of_freedom(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "outputs": [], + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "source": [ + "for o in order:\n", + " print(o[0].name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "outputs": [], + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "outputs": [], + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"fs.R101\";\n", + " - termination condition: infeasible\n", + " - message from solver: Ipopt 3.13.2\\x3a Converged to a locally infeasible\n", + " point. Problem may be infeasible.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"fs.R101\";\n", + " - termination condition: infeasible\n", + " - message from solver: Ipopt 3.13.2\\x3a Converged to a locally infeasible\n", + " point. Problem may be infeasible.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "source": [ + "seq.run(m, function)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "outputs": [], + "source": [ + "from idaes.core.util.initialization import propagate_state" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "outputs": [], + "source": [ + "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "outputs": [], + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "outputs": [], + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "outputs": [], + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpoctkmbii\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpoctkmbii\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 155\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.74e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reallocating memory for MA57: lfact (10193)\n", + " 1r 0.0000000e+00 3.74e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 3.17e-07R 3\n", + " 2r 0.0000000e+00 6.21e+04 1.21e+03 3.6 3.74e+06 - 3.68e-03 3.56e-04f 1\n", + " 3r 0.0000000e+00 5.77e+04 1.09e+05 3.6 5.16e+05 - 9.43e-02 4.63e-03f 1\n", + " 4r 0.0000000e+00 5.24e+04 6.21e+04 3.6 3.34e+03 - 2.55e-01 9.98e-02f 1\n", + " 5r 0.0000000e+00 6.56e+04 1.25e+05 3.6 1.51e+02 - 6.91e-01 4.02e-01f 1\n", + " 6r 0.0000000e+00 4.50e+04 2.67e+04 3.6 3.07e+01 - 1.00e+00 7.13e-01f 1\n", + " 7r 0.0000000e+00 1.83e+04 7.35e+03 3.6 3.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 8r 0.0000000e+00 3.31e+04 4.68e+03 2.9 3.73e+01 - 7.83e-01 8.25e-01f 1\n", + " 9r 0.0000000e+00 1.06e+04 6.58e+02 2.9 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 6.29e+03 4.93e+02 2.9 2.70e+01 - 1.00e+00 1.00e+00h 1\n", + " 11r 0.0000000e+00 5.23e+04 5.25e+02 2.2 2.33e+01 - 9.63e-01 9.78e-01f 1\n", + " 12r 0.0000000e+00 7.01e+03 1.04e+02 2.2 2.10e+01 - 1.00e+00 1.00e+00f 1\n", + " 13r 0.0000000e+00 8.17e+02 1.95e+01 2.2 5.26e+00 - 1.00e+00 1.00e+00f 1\n", + " 14r 0.0000000e+00 5.65e+03 7.52e+02 1.5 1.79e+01 - 8.36e-01 9.57e-01f 1\n", + " 15r 0.0000000e+00 1.39e+04 5.80e+02 1.5 7.56e+01 - 7.87e-01 5.50e-01f 1\n", + " 16r 0.0000000e+00 1.86e+04 4.51e+02 1.5 1.21e+01 - 6.10e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.25e+04 2.51e+02 1.5 1.27e+01 - 7.28e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 8.69e+02 4.46e+01 1.5 9.42e+00 - 1.00e+00 1.00e+00h 1\n", + " 19r 0.0000000e+00 2.75e+02 1.30e+00 1.5 2.78e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 3.71e+03 2.13e+02 0.8 1.88e+01 - 9.33e-01 9.68e-01f 1\n", + " 21r 0.0000000e+00 9.91e+01 1.22e+02 0.8 1.24e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 2.87e+01 1.01e+03 0.8 4.55e-01 1.5 3.90e-01 9.98e-01H 1\n", + " 23r 0.0000000e+00 4.95e+02 1.46e+02 0.8 4.53e-01 1.0 1.00e+00 9.27e-01f 1\n", + " 24r 0.0000000e+00 4.75e+02 3.38e+02 0.8 4.95e-01 1.5 6.73e-01 8.53e-01f 1\n", + " 25r 0.0000000e+00 2.04e+02 7.82e+01 0.8 7.99e-02 2.8 1.00e+00 1.00e+00f 1\n", + " 26r 0.0000000e+00 2.86e+02 1.37e+02 0.8 9.62e-01 2.3 2.38e-01 2.31e-01f 1\n", + " 27r 0.0000000e+00 2.57e+02 7.76e+02 0.8 7.36e-01 1.8 4.15e-01 7.40e-02f 1\n", + " 28r 0.0000000e+00 2.55e+02 7.67e+02 0.8 3.59e+02 - 2.06e-02 8.24e-03f 2\n", + " 29r 0.0000000e+00 3.58e+02 5.95e+01 0.8 1.21e-01 1.4 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 8.66e+02 2.43e+02 0.8 6.93e+01 - 9.31e-01 4.48e-01f 2\n", + " 31r 0.0000000e+00 7.82e+02 2.67e+02 0.8 5.52e+00 0.9 8.90e-02 9.64e-02h 1\n", + " 32r 0.0000000e+00 6.93e+02 1.87e+02 0.8 2.84e+01 - 5.79e-02 1.48e-01h 1\n", + " 33r 0.0000000e+00 5.58e+02 1.23e+02 0.8 2.39e+01 - 2.97e-01 3.32e-01f 1\n", + " 34r 0.0000000e+00 4.53e+02 2.25e+02 0.8 1.58e+01 - 1.41e-01 2.10e-01f 1\n", + " 35r 0.0000000e+00 4.31e+02 1.86e+02 0.8 1.74e+01 - 2.72e-02 5.15e-02h 1\n", + " 36r 0.0000000e+00 4.28e+02 3.00e+02 0.8 4.39e+01 - 1.73e-03 5.76e-03h 1\n", + " 37r 0.0000000e+00 4.28e+02 2.99e+02 0.8 1.11e+03 - 2.19e-05 2.25e-04h 1\n", + " 38r 0.0000000e+00 4.28e+02 6.92e+02 0.8 2.39e+02 1.3 2.42e-03 1.96e-04f 1\n", + " 39r 0.0000000e+00 4.12e+02 1.12e+04 0.8 1.90e+01 - 7.18e-01 3.76e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.29e+02 2.87e+02 0.8 1.04e+01 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 4.97e+01 7.12e+02 0.8 5.85e+00 - 5.86e-01 6.18e-01h 1\n", + " 42r 0.0000000e+00 1.60e+00 1.99e+02 0.8 7.12e-01 0.8 1.00e+00 1.00e+00f 1\n", + " 43r 0.0000000e+00 2.18e+01 1.63e+02 0.1 6.04e+01 0.4 1.22e-02 7.09e-03f 1\n", + " 44r 0.0000000e+00 7.21e+03 1.05e+03 0.1 1.64e+02 - 1.83e-01 7.12e-01f 1\n", + " 45r 0.0000000e+00 6.31e+03 7.50e+02 0.1 5.95e+01 - 1.09e-01 1.68e-01f 1\n", + " 46r 0.0000000e+00 6.22e+03 1.41e+03 0.1 9.02e+01 - 8.19e-04 1.38e-02f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 47r 0.0000000e+00 6.22e+03 1.41e+03 0.1 1.27e+02 0.8 1.98e-03 9.14e-04h 1\n", + " 48r 0.0000000e+00 6.21e+03 1.57e+03 0.1 2.55e+02 0.3 1.66e-05 7.85e-04h 1\n", + " 49r 0.0000000e+00 6.18e+03 1.56e+03 0.1 2.15e+01 0.7 2.64e-03 4.99e-03h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.18e+03 1.60e+03 0.1 1.55e+02 0.3 2.53e-05 2.61e-04h 1\n", + " 51r 0.0000000e+00 6.18e+03 1.67e+03 0.1 7.60e+01 1.6 1.06e-02 3.63e-04h 1\n", + " 52r 0.0000000e+00 5.80e+03 1.65e+03 0.1 2.59e+01 - 3.10e-02 6.80e-02f 1\n", + " 53r 0.0000000e+00 5.29e+03 1.04e+03 0.1 3.13e+01 - 8.78e-01 6.14e-01f 1\n", + " 54r 0.0000000e+00 2.06e+03 3.00e+02 0.1 3.76e+01 - 7.50e-01 1.00e+00h 1\n", + " 55r 0.0000000e+00 5.02e+01 1.17e+02 0.1 1.26e+01 - 1.00e+00 1.00e+00h 1\n", + " 56r 0.0000000e+00 4.11e+01 1.08e+02 0.1 4.23e+00 - 2.42e-01 1.84e-01h 1\n", + " 57r 0.0000000e+00 2.12e+01 5.27e+01 0.1 1.15e+00 - 7.37e-01 8.32e-01h 1\n", + " 58r 0.0000000e+00 4.74e+01 3.85e+01 0.1 1.60e+00 - 9.93e-01 1.00e+00f 1\n", + " 59r 0.0000000e+00 1.17e+01 3.25e+01 0.1 1.40e+00 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.21e+03 4.46e+01 -0.6 5.97e+01 - 7.60e-01 6.94e-01f 1\n", + " 61r 0.0000000e+00 1.54e+03 4.60e+00 -0.6 9.23e+01 - 1.00e+00 1.00e+00f 1\n", + " 62r 0.0000000e+00 1.21e+01 9.28e+00 -0.6 4.59e+01 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.83e+00 9.35e-02 -0.6 2.84e+00 - 1.00e+00 1.00e+00h 1\n", + " 64r 0.0000000e+00 1.11e+03 6.94e+01 -1.3 7.51e+01 - 9.02e-01 9.81e-01f 1\n", + " 65r 0.0000000e+00 7.93e+00 9.52e-01 -1.3 2.38e+01 - 1.00e+00 1.00e+00h 1\n", + " 66r 0.0000000e+00 1.78e+00 1.07e-01 -1.3 8.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 67r 0.0000000e+00 2.18e-01 1.01e-05 -1.3 3.94e-03 - 1.00e+00 1.00e+00h 1\n", + " 68r 0.0000000e+00 1.15e+03 4.78e+01 -4.5 7.86e+01 - 7.94e-01 8.05e-01f 1\n", + " 69r 0.0000000e+00 5.20e+02 1.43e+02 -4.5 2.20e+01 - 9.21e-01 5.55e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 2.62e+02 4.30e+02 -4.5 1.21e-02 1.1 9.09e-01 4.96e-01h 1\n", + " 71r 0.0000000e+00 6.29e+01 1.51e+02 -4.5 1.25e-02 0.6 9.00e-01 7.60e-01h 1\n", + " 72r 0.0000000e+00 9.72e+00 5.07e+01 -4.5 5.71e-02 0.2 9.11e-01 8.46e-01h 1\n", + " 73r 0.0000000e+00 2.40e-01 8.98e-01 -4.5 1.58e-01 -0.3 1.00e+00 9.91e-01h 1\n", + " 74r 0.0000000e+00 3.60e-01 1.74e+02 -4.5 3.96e+03 - 6.95e-03 2.59e-03f 1\n", + " 75r 0.0000000e+00 8.17e-01 3.02e+02 -4.5 9.81e+00 - 7.96e-02 1.55e-02h 1\n", + " 76r 0.0000000e+00 2.96e+02 1.34e+03 -4.5 3.56e+00 - 9.74e-02 3.29e-01h 1\n", + " 77r 0.0000000e+00 2.24e+02 1.38e+03 -4.5 2.48e-02 -0.8 1.00e+00 2.45e-01h 1\n", + " 78r 0.0000000e+00 1.29e+03 6.57e+02 -4.5 1.82e+00 - 6.97e-01 1.00e+00h 1\n", + " 79r 0.0000000e+00 2.01e+02 1.01e+02 -4.5 2.12e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 4.78e+00 7.47e-01 -4.5 3.32e-01 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 2.94e+00 2.75e-02 -4.5 2.59e-01 - 1.00e+00 1.00e+00h 1\n", + " 82r 0.0000000e+00 2.79e-01 2.57e-03 -4.5 2.99e-02 - 1.00e+00 1.00e+00h 1\n", + " 83r 0.0000000e+00 2.79e-01 4.06e-04 -4.5 4.57e-03 - 1.00e+00 1.00e+00h 1\n", + " 84r 0.0000000e+00 2.79e-01 1.25e-07 -4.5 8.34e-05 - 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 5.26e+01 1.09e+01 -6.8 7.12e-01 - 9.31e-01 8.92e-01f 1\n", + " 86r 0.0000000e+00 2.95e+01 4.47e+02 -6.8 1.59e-01 - 7.12e-01 4.40e-01h 1\n", + " 87r 0.0000000e+00 7.70e+00 1.01e+02 -6.8 9.53e-02 - 8.78e-01 7.65e-01h 1\n", + " 88r 0.0000000e+00 3.45e+00 1.42e+02 -6.8 9.16e-02 - 1.00e+00 7.55e-01h 1\n", + " 89r 0.0000000e+00 9.20e-01 4.87e+01 -6.8 1.08e-01 - 8.60e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90r 0.0000000e+00 8.31e-01 1.80e-01 -6.8 1.38e-01 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 2.83e-01 1.84e-01 -6.8 7.34e-02 - 1.00e+00 1.00e+00h 1\n", + " 92r 0.0000000e+00 2.83e-01 4.21e+02 -6.8 9.27e-01 - 1.19e-01 4.48e-03h 6\n", + " 93r 0.0000000e+00 2.83e-01 1.51e+02 -6.8 9.89e-06 -1.3 1.00e+00 1.03e-01h 1\n", + " 94r 0.0000000e+00 2.83e-01 3.45e+02 -6.8 1.02e+00 - 1.44e-01 2.36e-02h 3\n", + " 95r 0.0000000e+00 2.83e-01 2.09e+01 -6.8 6.98e-03 -1.7 3.75e-02 2.48e-02h 2\n", + " 96r 0.0000000e+00 2.83e-01 7.23e+00 -6.8 5.65e-04 -2.2 9.81e-01 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.20e+01 2.06e+02 -6.8 1.57e+00 - 1.00e+00 3.33e-01h 2\n", + " 98r 0.0000000e+00 1.19e+01 2.37e+01 -6.8 1.56e-02 - 1.00e+00 5.65e-03h 8\n", + " 99r 0.0000000e+00 1.18e+01 2.23e+01 -6.8 1.79e-02 - 1.00e+00 7.81e-03h 8\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 0.0000000e+00 1.18e+01 2.16e+01 -6.8 1.76e-02 - 1.00e+00 1.95e-03h 10\n", + " 101r 0.0000000e+00 1.18e+01 2.14e+01 -6.8 1.76e-02 - 1.00e+00 9.77e-04h 11\n", + " 102r 0.0000000e+00 1.18e+01 2.13e+01 -6.8 1.76e-02 - 1.00e+00 4.88e-04h 12\n", + " 103r 0.0000000e+00 2.90e-01 3.50e-04 -6.8 1.76e-02 - 1.00e+00 1.00e+00h 1\n", + " 104r 0.0000000e+00 7.03e+00 2.14e+02 -6.8 4.02e-01 - 5.84e-01 1.00e+00h 1\n", + " 105r 0.0000000e+00 2.96e-01 5.54e+01 -6.8 7.32e-02 - 2.26e-01 1.00e+00h 1\n", + " 106r 0.0000000e+00 2.96e-01 8.03e-05 -6.8 1.47e-04 -2.7 1.00e+00 1.00e+00h 1\n", + " 107r 0.0000000e+00 2.95e-01 4.46e+01 -6.8 1.04e-01 - 1.00e+00 5.00e-01h 2\n", + " 108r 0.0000000e+00 2.95e-01 1.34e-02 -6.8 1.91e-02 - 1.00e+00 1.00e+00h 1\n", + " 109r 0.0000000e+00 2.94e-01 1.41e-03 -6.8 3.97e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110r 0.0000000e+00 2.94e-01 9.14e-04 -6.8 2.67e-02 - 1.00e+00 1.00e+00h 1\n", + " 111r 0.0000000e+00 2.94e-01 4.70e-05 -6.8 1.04e-03 - 1.00e+00 1.00e+00h 1\n", + " 112r 0.0000000e+00 2.94e-01 1.32e-07 -6.8 7.16e-04 - 1.00e+00 1.00e+00h 1\n", + " 113r 0.0000000e+00 2.94e-01 1.82e-12 -6.8 2.28e-06 - 1.00e+00 1.00e+00h 1\n", + " 114r 0.0000000e+00 9.46e-01 5.08e+00 -9.0 2.12e-01 - 6.64e-01 6.35e-01h 1\n", + " 115r 0.0000000e+00 1.29e+01 9.86e+00 -9.0 5.14e-01 - 7.92e-01 7.53e-01h 1\n", + " 116r 0.0000000e+00 6.76e+00 1.53e+02 -9.0 2.57e-01 - 8.31e-01 6.76e-01h 1\n", + " 117r 0.0000000e+00 8.96e+00 2.11e+00 -9.0 1.62e-01 - 1.00e+00 1.00e+00h 1\n", + " 118r 0.0000000e+00 8.94e-01 8.15e-01 -9.0 8.76e-02 - 1.00e+00 1.00e+00h 1\n", + " 119r 0.0000000e+00 5.50e-01 2.30e-02 -9.0 1.13e-01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120r 0.0000000e+00 2.99e-01 1.49e-04 -9.0 1.27e-02 - 1.00e+00 1.00e+00h 1\n", + " 121r 0.0000000e+00 2.98e-01 2.05e-05 -9.0 1.10e-02 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 2.98e-01 2.86e-08 -9.0 5.44e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 122\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 4.6276843335396955e-07 4.6276843335396955e-07\n", + "Constraint violation....: 2.9835465732216782e-01 2.9835465732216782e-01\n", + "Complementarity.........: 9.0909090909100423e-10 9.0909090909100423e-10\n", + "Overall NLP error.......: 2.9835465732216782e-01 2.9835465732216782e-01\n", + "\n", + "\n", + "Number of objective function evaluations = 193\n", + "Number of objective gradient evaluations = 3\n", + "Number of equality constraint evaluations = 193\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 125\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 123\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.161\n", + "Total CPU secs in NLP function evaluations = 0.016\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "outputs": [], + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpg07cmjii\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpg07cmjii\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 155\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.74e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1r 0.0000000e+00 3.74e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 3.17e-07R 3\n", + " 2r 0.0000000e+00 6.21e+04 1.21e+03 3.6 3.74e+06 - 3.68e-03 3.56e-04f 1\n", + " 3r 0.0000000e+00 5.77e+04 1.01e+05 3.6 5.16e+05 - 8.85e-02 4.63e-03f 1\n", + " 4r 0.0000000e+00 5.27e+04 7.54e+04 3.6 3.55e+03 - 2.53e-01 9.39e-02f 1\n", + " 5r 0.0000000e+00 6.46e+04 1.25e+05 3.6 1.62e+02 - 6.86e-01 3.91e-01f 1\n", + " 6r 0.0000000e+00 4.60e+04 2.59e+04 3.6 3.07e+01 - 1.00e+00 7.29e-01f 1\n", + " 7r 0.0000000e+00 1.41e+04 8.03e+03 3.6 3.17e+01 - 1.00e+00 1.00e+00f 1\n", + " 8r 0.0000000e+00 3.34e+04 6.37e+03 2.9 3.71e+01 - 7.68e-01 8.25e-01f 1\n", + " 9r 0.0000000e+00 1.19e+04 7.40e+02 2.9 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 6.30e+03 4.59e+02 2.9 2.35e+01 - 1.00e+00 1.00e+00h 1\n", + " 11r 0.0000000e+00 5.23e+04 5.45e+02 2.2 2.33e+01 - 9.62e-01 9.77e-01f 1\n", + " 12r 0.0000000e+00 7.00e+03 1.04e+02 2.2 2.11e+01 - 1.00e+00 1.00e+00f 1\n", + " 13r 0.0000000e+00 7.13e+02 1.92e+01 2.2 5.17e+00 - 1.00e+00 1.00e+00f 1\n", + " 14r 0.0000000e+00 5.67e+03 7.52e+02 1.5 1.80e+01 - 8.36e-01 9.57e-01f 1\n", + " 15r 0.0000000e+00 1.39e+04 5.79e+02 1.5 7.56e+01 - 7.87e-01 5.50e-01f 1\n", + " 16r 0.0000000e+00 1.86e+04 4.46e+02 1.5 1.21e+01 - 6.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+04 2.49e+02 1.5 1.26e+01 - 7.29e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 8.65e+02 4.42e+01 1.5 9.39e+00 - 1.00e+00 1.00e+00h 1\n", + " 19r 0.0000000e+00 2.73e+02 1.31e+00 1.5 2.73e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 3.72e+03 2.13e+02 0.8 1.88e+01 - 9.33e-01 9.68e-01f 1\n", + " 21r 0.0000000e+00 9.91e+01 1.22e+02 0.8 1.24e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 2.89e+01 1.01e+03 0.8 4.57e-01 1.5 3.88e-01 9.92e-01H 1\n", + " 23r 0.0000000e+00 4.92e+02 1.65e+02 0.8 4.52e-01 1.0 1.00e+00 9.06e-01f 1\n", + " 24r 0.0000000e+00 4.89e+02 3.27e+02 0.8 4.93e-01 1.5 6.74e-01 8.51e-01f 1\n", + " 25r 0.0000000e+00 2.08e+02 7.82e+01 0.8 7.90e-02 2.8 1.00e+00 1.00e+00f 1\n", + " 26r 0.0000000e+00 2.93e+02 1.41e+02 0.8 9.61e-01 2.3 2.45e-01 2.35e-01f 1\n", + " 27r 0.0000000e+00 2.70e+02 7.26e+02 0.8 8.43e-01 1.8 3.36e-01 6.18e-02f 1\n", + " 28r 0.0000000e+00 2.69e+02 7.21e+02 0.8 5.66e+02 - 1.20e-02 4.81e-03f 2\n", + " 29r 0.0000000e+00 4.15e+02 6.03e+01 0.8 1.17e-01 1.4 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 8.56e+02 2.58e+02 0.8 7.00e+01 - 9.49e-01 4.42e-01f 2\n", + " 31r 0.0000000e+00 6.84e+02 2.86e+02 0.8 2.71e+00 0.9 1.79e-01 2.01e-01h 1\n", + " 32r 0.0000000e+00 5.92e+02 1.69e+02 0.8 2.88e+01 - 1.34e-01 3.24e-01f 1\n", + " 33r 0.0000000e+00 4.89e+02 1.45e+02 0.8 1.92e+01 - 1.00e+00 1.00e+00f 1\n", + " 34r 0.0000000e+00 7.71e+00 5.04e+01 0.8 1.11e+00 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 8.63e+03 3.42e+01 -0.6 2.52e+01 - 6.33e-01 6.26e-01f 1\n", + " 36r 0.0000000e+00 5.46e+03 5.26e+02 -0.6 1.02e+00 0.4 6.69e-01 3.70e-01f 1\n", + " 37r 0.0000000e+00 2.30e+03 1.84e+02 -0.6 6.65e-01 0.8 6.29e-01 5.80e-01f 1\n", + " 38r 0.0000000e+00 9.77e+02 7.18e+01 -0.6 1.85e+00 0.4 4.96e-01 6.05e-01f 1\n", + " 39r 0.0000000e+00 7.39e+02 5.97e+01 -0.6 2.45e+00 -0.1 4.52e-01 4.94e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 8.88e+02 1.40e+02 -0.6 7.33e+00 -0.6 6.79e-01 3.09e-01h 1\n", + " 41r 0.0000000e+00 1.61e+01 1.29e+01 -0.6 3.68e-01 0.7 1.00e+00 1.00e+00h 1\n", + " 42r 0.0000000e+00 6.47e+01 6.22e+00 -0.6 9.57e-01 0.3 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 5.42e+02 5.88e+00 -0.6 3.02e+00 -0.2 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 1.31e+03 5.88e+01 -0.6 9.54e+00 -0.7 5.38e-01 4.31e-01h 1\n", + " 45r 0.0000000e+00 1.41e+03 2.73e+02 -0.6 1.19e+02 - 1.87e-01 1.21e-01h 1\n", + " 46r 0.0000000e+00 1.08e+03 3.24e+02 -0.6 1.37e+02 - 6.36e-01 4.65e-01f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 47r 0.0000000e+00 6.96e+02 2.77e+02 -0.6 8.41e+00 - 4.25e-01 3.72e-01h 1\n", + " 48r 0.0000000e+00 1.45e+02 1.84e+02 -0.6 8.64e+00 - 5.45e-01 7.92e-01h 1\n", + " 49r 0.0000000e+00 7.13e+01 3.91e+02 -0.6 2.50e+00 - 7.16e-01 5.13e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 4.36e+00 1.14e+02 -0.6 2.79e+00 - 1.00e+00 1.00e+00f 1\n", + " 51r 0.0000000e+00 6.03e-01 2.36e+01 -0.6 8.61e-01 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 6.61e-01 4.55e+00 -0.6 2.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 53r 0.0000000e+00 1.10e+03 6.90e+01 -1.3 7.52e+01 - 9.02e-01 9.81e-01f 1\n", + " 54r 0.0000000e+00 8.00e+00 8.01e-01 -1.3 2.37e+01 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 1.78e+00 1.07e-01 -1.3 8.16e-01 - 1.00e+00 1.00e+00h 1\n", + " 56r 0.0000000e+00 2.18e-01 5.40e-06 -1.3 3.90e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 1.15e+03 4.77e+01 -4.5 7.87e+01 - 7.94e-01 8.05e-01f 1\n", + " 58r 0.0000000e+00 5.17e+02 1.43e+02 -4.5 2.20e+01 - 9.21e-01 5.56e-01h 1\n", + " 59r 0.0000000e+00 2.84e+02 5.22e+02 -4.5 1.42e-01 -1.2 9.08e-01 4.51e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 5.10e+01 1.24e+02 -4.5 2.35e-01 -1.6 9.14e-01 8.21e-01h 1\n", + " 61r 0.0000000e+00 5.05e+01 4.54e+02 -4.5 4.49e+02 - 1.00e+00 2.18e-02h 1\n", + " 62r 0.0000000e+00 1.39e+03 2.01e+02 -4.5 3.30e+00 - 1.00e+00 9.24e-01h 1\n", + " 63r 0.0000000e+00 2.91e+02 7.48e+01 -4.5 1.78e-01 - 1.00e+00 7.97e-01h 1\n", + " 64r 0.0000000e+00 4.07e+00 2.17e+01 -4.5 7.87e-02 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.04e+00 2.05e+02 -4.5 5.95e-01 - 1.00e+00 2.50e-01h 3\n", + " 66r 0.0000000e+00 2.27e+00 1.18e+02 -4.5 5.27e-01 - 1.00e+00 2.50e-01h 3\n", + " 67r 0.0000000e+00 2.00e+00 6.21e+01 -4.5 3.35e-01 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 9.09e-01 8.92e-02 -4.5 1.44e-01 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 2.78e-01 2.22e-02 -4.5 6.01e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 2.78e-01 9.38e-05 -4.5 1.31e-03 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 5.15e+01 1.10e+01 -6.8 7.08e-01 - 9.31e-01 8.92e-01h 1\n", + " 72r 0.0000000e+00 2.90e+01 4.50e+02 -6.8 1.50e-01 - 7.13e-01 4.39e-01h 1\n", + " 73r 0.0000000e+00 7.89e+00 1.01e+02 -6.8 8.85e-02 - 8.77e-01 7.65e-01h 1\n", + " 74r 0.0000000e+00 2.97e+00 1.42e+02 -6.8 9.08e-02 - 1.00e+00 7.58e-01h 1\n", + " 75r 0.0000000e+00 8.82e-01 4.89e+01 -6.8 1.11e-01 - 8.59e-01 1.00e+00h 1\n", + " 76r 0.0000000e+00 7.58e-01 1.53e-01 -6.8 1.32e-01 - 1.00e+00 1.00e+00h 1\n", + " 77r 0.0000000e+00 2.82e-01 2.05e-01 -6.8 7.96e-02 - 1.00e+00 1.00e+00h 1\n", + " 78r 0.0000000e+00 2.82e-01 6.98e+01 -6.8 5.00e-01 - 2.24e-01 2.59e-01H 1\n", + " 79r 0.0000000e+00 2.82e-01 2.94e+02 -6.8 1.59e-01 - 1.00e+00 1.67e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 2.81e-01 1.89e+02 -6.8 4.85e-01 - 8.32e-02 9.31e-02f 2\n", + " 81r 0.0000000e+00 2.81e-01 5.14e+02 -6.8 7.87e-04 -2.1 4.98e-01 7.44e-01h 1\n", + " 82r 0.0000000e+00 2.81e-01 9.19e+02 -6.8 2.22e-04 -2.6 1.00e+00 2.63e-01h 1\n", + " 83r 0.0000000e+00 2.81e-01 1.65e-02 -6.8 9.95e-04 -3.1 1.00e+00 1.00e+00f 1\n", + " 84r 0.0000000e+00 7.23e+00 1.63e-01 -6.8 4.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 2.87e-01 2.33e-04 -6.8 9.28e-03 - 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 2.87e-01 1.97e+00 -6.8 5.56e-01 - 1.00e+00 1.22e-04h 14\n", + " 87r 0.0000000e+00 2.87e-01 2.46e+00 -6.8 5.00e-01 - 1.00e+00 1.22e-04h 14\n", + " 88r 0.0000000e+00 2.87e-01 2.58e+00 -6.8 4.78e-01 - 1.00e+00 1.22e-04h 14\n", + " 89r 0.0000000e+00 2.87e-01 2.62e+00 -6.8 4.70e-01 - 1.00e+00 1.22e-04h 14\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.67e-01 - 1.00e+00 1.22e-04h 14\n", + " 91r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.66e-01 - 1.00e+00 1.22e-04h 14\n", + " 92r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 93r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 94r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 95r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 96r 0.0000000e+00 9.42e+00 1.88e-02 -6.8 4.65e-01 - 1.00e+00 1.00e+00w 1\n", + " 97r 0.0000000e+00 2.93e-01 1.19e-06 -6.8 8.82e-04 - 1.00e+00 1.00e+00w 1\n", + " 98r 0.0000000e+00 2.93e-01 5.78e-06 -6.8 2.07e-03 - 1.00e+00 1.00e+00w 1\n", + " 99r 0.0000000e+00 2.93e-01 2.04e-11 -6.8 4.54e-06 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 0.0000000e+00 7.74e-01 4.78e+00 -9.0 2.09e-01 - 6.64e-01 6.37e-01h 1\n", + " 101r 0.0000000e+00 8.46e+00 3.40e+01 -9.0 3.17e-01 - 9.10e-01 7.63e-01h 1\n", + " 102r 0.0000000e+00 4.04e+00 2.19e+02 -9.0 2.21e-01 - 8.62e-01 6.33e-01h 1\n", + " 103r 0.0000000e+00 7.03e+00 1.45e+00 -9.0 1.41e-01 - 1.00e+00 1.00e+00h 1\n", + " 104r 0.0000000e+00 7.21e-01 5.48e-01 -9.0 9.46e-02 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 2.97e-01 1.72e-02 -9.0 7.60e-02 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 2.97e-01 6.61e-05 -9.0 2.35e-02 - 1.00e+00 1.00e+00h 1\n", + " 107r 0.0000000e+00 2.97e-01 1.83e-06 -9.0 1.21e-03 - 1.00e+00 1.00e+00h 1\n", + " 108r 0.0000000e+00 2.97e-01 3.43e-08 -9.0 2.97e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 108\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 3.0151134107357916e-07 3.0151134107357916e-07\n", + "Constraint violation....: 2.9731578903766509e-01 2.9731578903766509e-01\n", + "Complementarity.........: 9.0909090909099699e-10 9.0909090909099699e-10\n", + "Overall NLP error.......: 2.9731578903766509e-01 2.9731578903766509e-01\n", + "\n", + "\n", + "Number of objective function evaluations = 271\n", + "Number of objective gradient evaluations = 3\n", + "Number of equality constraint evaluations = 271\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 111\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 109\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.155\n", + "Total CPU secs in NLP function evaluations = 0.015\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate Liq mole / second 0.30001 2.0000e-05 0.29609 4.7359e-12 0.22506 1.0000e-08 0.30007 8.0134e-09 8.0151e-09 1.0000e-08 0.30007 2.0077e-09\n", + " Total Molar Flowrate Vap mole / second 4.0000e-05 0.32002 0.32272 0.61696 0.075008 2.0137e-10 1.0000e-08 1.5056e-10 1.3399e-10 1.9913e-08 1.0000e-08 4.0429e-11\n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 3.3332e-05 0.50000 0.00012935 5.9851e-05 1.0000e-20 1.0000e-20 1.0000e-20 0.0016277 0.0017605 1.0000e-20 1.0000e-20 0.0038222\n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.99997 0.50000 0.99987 0.99994 1.0000 1.0000 1.0000 0.99837 0.99824 1.0000 1.0000 0.99618\n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.25000 3.1248e-05 5.2698e-06 6.4834e-05 1.0000e-20 1.0000e-20 1.0000e-20 0.00017956 0.00019422 1.0000e-20 1.0000e-20 0.00042167\n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.25000 3.1248e-05 0.012327 0.48630 1.0000 0.037785 0.037785 0.037723 0.037718 0.51680 0.51680 0.037640\n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.25000 0.93744 0.92592 0.48184 1.3527e-09 0.49388 0.49388 0.49395 0.49398 0.24801 0.24801 0.49387\n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.25000 0.062496 0.061748 0.031794 1.2842e-09 0.46834 0.46834 0.46815 0.46810 0.23519 0.23519 0.46807\n", + " Temperature kelvin 303.20 303.20 300.45 600.00 664.03 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "source": [ + "m.fs.report()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 225939.23444372677\n" + ] + } + ], + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 2575.4 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 0.30007 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.037785 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.49388 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.46834 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.30007 \n", + " flow_mol_phase Vap mole / second - 1.9913e-08 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 1.0000e-20 1.0000e-20 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 1.0000 1.0000 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 1.0000e-20 1.0000e-20 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.51680 0.51680 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.24801 0.24801 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.23519 0.23519 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 1.934999854274726e-20\n" + ] + } + ], + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate Liq mole / second 0.22506 1.0000e-08 \n", + "Total Molar Flowrate Vap mole / second 0.075008 2.0137e-10 \n", + "Total Mole Fraction ('Liq', 'benzene') dimensionless 1.0000e-20 1.0000e-20 \n", + "Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 1.0000 \n", + "Total Mole Fraction ('Vap', 'benzene') dimensionless 1.0000e-20 1.0000e-20 \n", + "Total Mole Fraction ('Vap', 'toluene') dimensionless 1.0000 0.037785 \n", + "Total Mole Fraction ('Vap', 'hydrogen') dimensionless 1.3527e-09 0.49388 \n", + "Total Mole Fraction ('Vap', 'methane') dimensionless 1.2842e-09 0.46834 \n", + "Temperature kelvin 664.03 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "outputs": [], + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "outputs": [], + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "outputs": [], + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpl0wqmn_f\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpl0wqmn_f\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 159\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 2.2593923e+05 4.10e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 2.2592658e+05 4.10e+04 6.94e+00 -1.0 2.26e+06 - 1.24e-06 1.27e-06f 1\n", + " 2 2.2592558e+05 4.10e+04 3.83e+02 -1.0 1.09e+07 - 2.51e-06 1.27e-08f 1\n", + " 3 2.2575143e+05 4.10e+04 9.02e+03 -1.0 2.27e+09 - 2.63e-07 1.12e-08f 1\n", + " 4 2.1959194e+05 4.10e+04 5.77e+03 -1.0 2.25e+09 - 2.72e-07 3.98e-07f 1\n", + " 5 1.8296150e+05 3.46e+05 1.20e+05 -1.0 1.14e+09 - 7.70e-07 4.70e-06f 1\n", + " 6 1.8296150e+05 3.45e+05 4.95e+07 -1.0 1.99e+04 6.0 1.10e-01 2.49e-03h 1\n", + " 7 1.8308684e+05 3.45e+05 1.07e+10 -1.0 1.59e+07 - 4.38e-11 2.97e-05h 1\n", + " 8 1.8308686e+05 3.45e+05 1.07e+10 -1.0 3.47e+04 5.5 2.57e-08 1.27e-06f 2\n", + " 9 1.8308346e+05 3.45e+05 1.07e+10 -1.0 2.33e+06 - 1.28e-06 1.28e-06f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 1.8308346e+05 3.45e+05 9.99e+02 5.5 0.00e+00 - 0.00e+00 6.41e-09R 2\n", + " 11r 1.8308366e+05 3.44e+05 6.06e+03 5.5 3.59e+08 - 9.52e-05 2.75e-06f 1\n", + " 12r 1.8308341e+05 3.96e+04 6.44e+03 3.4 3.13e+08 - 4.75e-04 1.01e-03f 1\n", + " 13 1.8245986e+05 3.96e+04 3.21e+03 -1.0 9.17e+06 - 1.24e-04 1.01e-05f 1\n", + " 14 1.8245424e+05 3.96e+04 4.69e+06 -1.0 8.13e+06 - 1.38e-04 1.01e-07f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 15 1.8245406e+05 3.96e+04 8.01e+11 -1.0 5.70e+07 - 3.66e-04 1.06e-09f 2\n", + " 16 1.8163981e+05 3.96e+04 1.52e+12 -1.0 5.47e+08 - 2.78e-05 1.46e-05f 1\n", + " 17r 1.8163981e+05 3.96e+04 9.99e+02 4.6 0.00e+00 - 0.00e+00 1.32e-12R 2\n", + " 18r 1.8164024e+05 5.96e+04 6.63e+04 4.6 3.30e+07 - 1.77e-02 1.18e-04f 1\n", + " 19r 1.8164102e+05 4.78e+04 6.11e+04 3.2 1.72e+06 - 1.38e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 1.8164265e+05 4.73e+04 2.42e+04 3.2 2.06e+06 - 6.74e-01 1.03e-02f 1\n", + " 21r 1.8163776e+05 5.59e+04 1.44e+04 3.2 1.58e+03 - 4.29e-01 4.00e-01f 1\n", + " 22r 1.8168500e+05 4.59e+04 2.12e+03 3.2 6.14e+02 - 9.01e-01 8.37e-01f 1\n", + " 23r 1.8167353e+05 7.43e+04 2.27e+03 3.2 1.36e+02 - 3.19e-01 3.02e-01f 1\n", + " 24r 1.8153947e+05 5.07e+04 1.27e+04 3.2 6.53e+01 - 7.65e-01 1.00e+00f 1\n", + " 25r 1.8153947e+05 4.53e+04 1.69e+04 3.2 1.56e+01 4.0 1.07e-01 1.08e-01h 1\n", + " 26r 1.8153947e+05 2.41e+04 6.04e+04 3.2 1.81e+01 3.5 8.20e-01 1.00e+00f 1\n", + " 27 3.9962752e+04 2.41e+04 8.65e+01 -1.0 1.51e+07 - 1.07e-03 1.07e-03f 1\n", + " 28 1.7595823e+04 2.41e+04 1.10e+02 -1.0 2.01e+06 - 8.21e-03 1.19e-03f 1\n", + " 29 -1.6176446e+04 2.40e+04 4.65e+02 -1.0 1.41e+06 - 6.16e-03 4.06e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 -1.6503845e+04 2.40e+04 4.67e+02 -1.0 1.60e+05 - 5.34e-02 4.11e-04f 1\n", + " 31 -1.6103557e+04 2.39e+04 1.51e+04 -1.0 5.35e+04 - 6.91e-02 1.53e-03h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 32 -1.3109479e+04 2.37e+04 3.61e+04 -1.0 5.32e+04 - 1.16e-01 1.14e-02h 3\n", + " 33 -9.8778958e+03 2.34e+04 8.31e+04 -1.0 5.10e+04 - 2.78e-01 1.32e-02h 3\n", + " 34 -6.1943183e+03 2.30e+04 1.45e+05 -1.0 4.89e+04 - 5.07e-01 1.61e-02h 3\n", + " 35 -1.6595473e+03 2.25e+04 1.62e+05 -1.0 4.68e+04 - 3.19e-01 2.13e-02h 3\n", + " 36 5.4794139e+03 2.18e+04 1.85e+05 -1.0 4.46e+04 - 6.87e-01 3.60e-02h 3\n", + " 37 1.6365098e+04 2.05e+04 1.79e+05 -1.0 4.17e+04 - 3.54e-01 6.02e-02h 3\n", + " 38 2.7740530e+04 1.92e+04 1.68e+05 -1.0 3.80e+04 - 2.00e-01 7.01e-02h 3\n", + " 39 3.9763721e+04 1.78e+04 1.56e+05 -1.0 3.48e+04 - 2.45e-01 8.02e-02h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 5.2469134e+04 1.64e+04 1.44e+05 -1.0 3.21e+04 - 3.86e-01 9.05e-02h 3\n", + " 41 6.5791945e+04 1.49e+04 1.34e+05 -1.0 2.96e+04 - 6.07e-01 1.01e-01h 3\n", + " 42 1.2096642e+05 1.17e+04 8.09e+04 -1.0 2.75e+04 - 8.69e-01 4.43e-01w 1\n", + " 43 1.3345225e+05 1.02e+04 9.69e+04 -1.0 2.10e+04 - 9.90e-01 1.33e-01w 1\n", + " 44 1.3364425e+05 1.02e+04 1.48e+05 -1.0 2.14e+04 - 1.00e+00 2.24e-03w 1\n", + " 45 7.9585562e+04 1.35e+04 1.27e+05 -1.0 2.14e+04 - 8.69e-01 1.11e-01h 2\n", + " 46 9.2643927e+04 1.22e+04 1.21e+05 -1.0 2.69e+04 - 9.90e-01 1.12e-01h 3\n", + " 47 1.1662879e+05 1.01e+04 1.01e+05 -1.0 2.65e+04 - 1.00e+00 2.21e-01h 2\n", + " 48 1.5635635e+05 6.66e+03 7.23e+04 -1.0 2.30e+04 - 1.00e+00 4.07e-01H 1\n", + " 49 1.5677484e+05 6.62e+03 9.35e+04 -1.0 1.77e+04 - 1.00e+00 6.00e-03h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 1.5677903e+05 6.62e+03 9.06e+07 -1.0 1.77e+04 - 1.00e+00 6.03e-05h 1\n", + " 51r 1.5677903e+05 6.62e+03 1.00e+03 3.8 0.00e+00 - 0.00e+00 3.01e-07R 2\n", + " 52r 1.5677921e+05 2.60e+03 1.79e+03 3.8 6.62e+06 - 1.08e-02 9.90e-04f 1\n", + " 53 1.5639242e+05 2.60e+03 1.00e+02 -1.0 1.25e+05 - 5.02e-02 4.91e-04f 1\n", + " 54 1.5638540e+05 2.58e+03 7.78e+02 -1.0 1.53e+04 - 3.61e-01 7.65e-03h 1\n", + " 55 1.5639044e+05 2.58e+03 3.43e+06 -1.0 1.52e+04 - 7.08e-01 7.69e-05h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 56r 1.5639044e+05 2.58e+03 1.00e+03 3.4 0.00e+00 - 0.00e+00 3.85e-07R 2\n", + " 57r 1.5639078e+05 7.01e+02 9.95e+02 3.4 2.58e+06 - 5.78e-03 9.91e-04f 1\n", + " 58 1.5614585e+05 7.00e+02 1.38e+02 -1.0 9.14e+04 - 6.54e-02 4.74e-04f 1\n", + " 59 1.5624013e+05 6.99e+02 4.69e+03 -1.0 1.57e+04 - 5.04e-01 2.61e-03h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 1.5624202e+05 6.99e+02 1.47e+08 -1.0 1.57e+04 - 8.22e-01 2.62e-05h 1\n", + " 61r 1.5624202e+05 6.99e+02 1.00e+03 2.8 0.00e+00 - 0.00e+00 1.31e-07R 2\n", + " 62r 1.5624284e+05 1.84e+02 9.98e+02 2.8 6.99e+05 - 2.70e-03 9.90e-04f 1\n", + " 63 1.5604488e+05 1.84e+02 1.65e+02 -1.0 7.47e+04 - 7.78e-02 4.95e-04f 1\n", + " 64 1.5606175e+05 1.84e+02 1.65e+05 -1.0 1.59e+04 - 5.42e-01 3.40e-04h 1\n", + " 65r 1.5606175e+05 1.84e+02 1.00e+03 2.3 0.00e+00 - 0.00e+00 4.26e-07R 4\n", + " 66r 1.5606221e+05 4.72e+01 4.65e+03 2.3 1.84e+05 - 3.00e-01 9.90e-04f 1\n", + " 67 1.5598771e+05 4.72e+01 4.39e+02 -1.0 6.50e+04 - 8.77e-02 2.22e-04f 1\n", + " 68r 1.5598771e+05 4.72e+01 9.99e+02 1.7 0.00e+00 - 0.00e+00 2.77e-07R 4\n", + " 69r 1.5598853e+05 1.22e+01 1.33e+03 1.7 4.72e+04 - 3.27e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 1.5594804e+05 1.22e+01 7.89e+02 -1.0 6.09e+04 - 9.21e-02 1.30e-04f 1\n", + " 71r 1.5594804e+05 1.22e+01 9.99e+02 1.1 0.00e+00 - 0.00e+00 3.24e-07R 3\n", + " 72r 1.5594931e+05 5.34e+01 9.49e+02 1.1 1.22e+04 - 1.28e-01 9.90e-04f 1\n", + " 73r 1.5602328e+05 8.38e+03 8.47e+02 1.1 1.82e+02 - 3.97e-01 1.18e-01f 1\n", + " 74r 1.5611223e+05 5.32e+03 5.09e+02 1.1 1.27e+02 - 4.87e-01 3.88e-01f 1\n", + " 75r 1.5611538e+05 4.46e+03 9.27e+02 1.1 4.35e+01 - 3.30e-01 2.08e-01f 1\n", + " 76r 1.5618738e+05 4.27e+03 3.31e+02 1.1 6.22e+01 - 8.72e-01 5.98e-01f 1\n", + " 77r 1.5626949e+05 2.10e+04 5.81e+03 1.1 2.66e+02 - 6.87e-01 1.00e+00f 1\n", + " 78r 1.5626950e+05 9.45e+02 1.67e+03 1.1 2.44e+00 0.0 9.93e-01 9.56e-01h 1\n", + " 79r 1.5633952e+05 1.55e+03 6.08e+02 1.1 7.00e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 1.5642050e+05 1.38e+02 4.09e+01 1.1 1.25e+01 - 1.00e+00 1.00e+00h 1\n", + " 81r 1.5640166e+05 1.18e+00 1.13e+00 1.1 2.52e+00 - 1.00e+00 1.00e+00h 1\n", + " 82 1.4211718e+05 4.18e+02 7.70e+02 -1.0 7.62e+05 - 5.86e-03 2.54e-03f 1\n", + " 83r 1.4211718e+05 4.18e+02 9.99e+02 2.6 0.00e+00 - 0.00e+00 4.73e-07R 15\n", + " 84r 1.4211760e+05 9.63e+01 7.10e+03 2.6 4.18e+05 - 2.71e-02 9.90e-04f 1\n", + " 85 1.4189541e+05 9.64e+01 3.92e+02 -1.0 3.81e+05 - 1.62e-02 7.48e-05f 1\n", + " 86 1.4037132e+05 2.61e+03 1.06e+03 -1.0 1.60e+04 - 3.64e-02 1.33e-02f 1\n", + " 87 1.4037496e+05 2.61e+03 1.03e+06 -1.0 2.99e+04 - 9.60e-02 1.34e-04h 1\n", + " 88r 1.4037496e+05 2.61e+03 1.00e+03 3.4 0.00e+00 - 0.00e+00 3.35e-07R 3\n", + " 89r 1.4037548e+05 1.23e+03 1.25e+04 3.4 2.61e+06 - 2.16e-02 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 1.3159180e+05 1.24e+03 1.40e+01 -1.0 1.15e+06 - 1.26e-02 8.35e-04f 1\n", + " 91 1.3048033e+05 1.24e+03 5.90e+01 -1.0 5.18e+04 - 2.81e-02 2.55e-03f 1\n", + " 92 1.3047951e+05 1.24e+03 2.51e+05 -1.0 3.24e+04 - 1.03e-01 2.56e-05f 1\n", + " 93r 1.3047951e+05 1.24e+03 1.00e+03 3.1 0.00e+00 - 0.00e+00 1.28e-07R 2\n", + " 94r 1.3047961e+05 3.22e+02 7.99e+03 3.1 1.24e+06 - 1.28e-01 9.91e-04f 1\n", + " 95 1.2799595e+05 3.22e+02 3.48e+01 -1.0 2.84e+05 - 2.91e-02 8.14e-04f 1\n", + " 96 1.2798856e+05 3.21e+02 2.37e+03 -1.0 3.80e+04 - 8.68e-02 7.83e-04f 1\n", + " 97r 1.2798856e+05 3.21e+02 1.00e+03 2.5 0.00e+00 - 0.00e+00 4.90e-07R 5\n", + " 98r 1.2798821e+05 8.75e+01 6.36e+03 2.5 3.21e+05 - 3.92e-01 9.90e-04f 1\n", + " 99 1.2802319e+05 8.74e+01 1.07e+04 -1.0 4.00e+04 - 1.87e-01 4.16e-04h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 1.2802319e+05 8.74e+01 1.00e+03 1.9 0.00e+00 - 0.00e+00 2.60e-07R 5\n", + " 101r 1.2802286e+05 2.25e+01 1.59e+03 1.9 8.74e+04 - 3.57e-01 9.90e-04f 1\n", + " 102 1.2803524e+05 2.24e+01 3.21e+05 -1.0 4.04e+04 - 3.46e-01 1.15e-04h 1\n", + " 103r 1.2803524e+05 2.24e+01 1.00e+03 1.4 0.00e+00 - 0.00e+00 2.87e-07R 3\n", + " 104r 1.2803522e+05 5.73e+00 9.93e+02 1.4 2.24e+04 - 3.75e-01 9.90e-04f 1\n", + " 105 1.2801361e+05 5.73e+00 1.41e+03 -1.0 5.87e+04 - 3.71e-02 2.95e-05f 1\n", + " 106r 1.2801361e+05 5.73e+00 1.00e+03 0.8 0.00e+00 - 0.00e+00 1.48e-07R 2\n", + " 107r 1.2801478e+05 2.68e+00 9.89e+02 0.8 5.73e+03 - 8.71e-02 9.90e-04f 1\n", + " 108 1.2800949e+05 2.68e+00 5.60e+03 -1.0 5.63e+04 - 3.78e-02 7.54e-06f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 109r 1.2800949e+05 2.68e+00 1.00e+03 0.4 0.00e+00 - 0.00e+00 3.77e-08R 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110r 1.2801166e+05 3.81e+00 9.93e+02 0.4 2.68e+03 - 3.82e-02 9.90e-04f 1\n", + " 111r 1.2802445e+05 6.14e+02 9.64e+02 0.4 3.09e+02 - 2.66e-02 2.94e-02f 1\n", + " 112r 1.2806075e+05 1.08e+03 8.98e+02 0.4 1.58e+02 - 2.79e-01 5.62e-02f 1\n", + " 113r 1.2831404e+05 1.07e+03 6.34e+02 0.4 1.43e+02 - 7.40e-01 3.03e-01f 1\n", + " 114r 1.2886030e+05 3.98e+03 2.01e+02 0.4 5.86e+01 - 9.64e-01 8.55e-01f 1\n", + " 115r 1.2885846e+05 5.59e+03 3.81e+03 0.4 1.76e+01 -2.0 7.49e-01 9.89e-01F 1\n", + " 116r 1.2885837e+05 5.02e+03 1.59e+03 0.4 3.19e+01 -1.6 1.26e-01 1.01e-01h 1\n", + " 117r 1.2875688e+05 7.27e+03 8.69e+03 0.4 1.70e+02 - 9.01e-01 6.08e-01H 1\n", + " 118r 1.2861391e+05 1.91e+03 2.32e+03 0.4 6.76e+01 - 3.09e-01 4.96e-01h 1\n", + " 119r 1.2861391e+05 1.18e+03 1.30e+03 0.4 7.62e-01 0.7 2.63e-01 3.79e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120r 1.2861391e+05 1.50e+01 1.60e+03 0.4 1.12e+00 0.2 1.00e+00 1.00e+00f 1\n", + " 121r 1.2855214e+05 1.41e+03 6.30e+02 0.4 2.14e+02 - 7.06e-01 6.45e-01F 1\n", + " 122r 1.2854036e+05 1.62e+02 2.13e+01 0.4 1.05e+01 - 1.00e+00 1.00e+00f 1\n", + " 123r 1.2854284e+05 6.41e+01 1.88e+00 0.4 5.18e+00 - 1.00e+00 1.00e+00h 1\n", + " 124r 1.2854112e+05 1.24e+00 5.76e-02 0.4 5.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 125 1.2853731e+05 8.25e+00 8.46e+01 -1.0 3.52e+04 - 2.13e-03 1.10e-04f 6\n", + " 126 1.2853574e+05 1.02e+01 1.68e+02 -1.0 3.46e+04 - 3.78e-03 5.51e-05f 7\n", + " 127 1.2853471e+05 1.22e+01 3.97e+02 -1.0 3.51e+04 - 5.15e-03 5.52e-05f 7\n", + " 128 1.2853431e+05 1.41e+01 9.42e+02 -1.0 3.57e+04 - 5.14e-03 5.54e-05f 7\n", + " 129r 1.2853431e+05 1.41e+01 9.99e+02 1.2 0.00e+00 - 0.00e+00 4.36e-07R 14\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130r 1.2853521e+05 3.27e+00 3.14e+03 1.2 1.41e+04 - 6.27e-02 9.90e-04f 1\n", + " 131 1.2034467e+05 2.66e+02 3.47e+02 -1.0 1.47e+06 - 2.72e-03 6.73e-04f 1\n", + " 132 1.2022266e+05 4.31e+03 1.11e+03 -1.0 2.32e+04 - 6.56e-03 2.99e-03f 1\n", + " 133r 1.2022266e+05 4.31e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 4.67e-07R 7\n", + " 134r 1.2022335e+05 8.51e+03 7.19e+03 3.6 4.31e+06 - 1.68e-02 9.90e-04f 1\n", + " 135r 1.2022365e+05 8.36e+03 7.04e+03 2.2 5.51e+04 - 8.33e-01 1.76e-02f 1\n", + " 136r 1.2028738e+05 2.34e+05 4.43e+03 2.2 4.33e+02 - 5.63e-01 8.32e-01f 1\n", + " 137r 1.2028745e+05 8.35e+04 1.36e+03 2.2 1.19e+01 0.0 5.50e-01 7.32e-01f 1\n", + " 138r 1.2031198e+05 5.29e+04 7.87e+02 2.2 1.46e+02 - 6.30e-01 6.77e-01f 1\n", + " 139r 1.2030652e+05 2.46e+04 1.31e+03 2.2 5.31e+01 - 9.14e-01 8.25e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 1.2030840e+05 2.40e+04 1.29e+03 2.2 3.56e+01 - 1.86e-02 2.50e-02h 1\n", + " 141r 1.2030840e+05 2.36e+04 1.25e+03 2.2 9.18e+00 2.2 3.84e-02 1.35e-02h 1\n", + " 142r 1.2033359e+05 1.95e+04 8.08e+03 2.2 4.55e+01 - 5.22e-01 2.17e-01f 1\n", + " 143r 1.2038554e+05 3.79e+04 1.15e+03 2.2 5.04e+01 - 1.00e+00 1.00e+00f 1\n", + " 144r 1.2036898e+05 1.43e+04 8.09e+02 2.2 2.28e+01 - 1.00e+00 1.00e+00f 1\n", + " 145r 1.2047190e+05 5.00e+03 3.01e+02 2.2 5.23e+01 - 1.00e+00 7.53e-01h 1\n", + " 146r 1.2043452e+05 2.24e+03 2.42e+03 2.2 1.02e+01 - 1.00e+00 5.61e-01f 1\n", + " 147r 1.2041013e+05 4.32e+03 1.02e+03 2.2 1.51e+01 - 1.00e+00 5.72e-01f 1\n", + " 148r 1.2041937e+05 4.84e+02 1.91e+02 2.2 3.50e+00 - 1.00e+00 1.00e+00f 1\n", + " 149 1.1303874e+05 5.57e+03 4.76e+02 -1.0 2.96e+05 - 3.61e-03 2.13e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 1.1050904e+05 5.53e+03 3.99e+02 -1.0 1.56e+05 - 8.49e-03 1.87e-03f 1\n", + " 151 1.1027960e+05 5.52e+03 4.08e+02 -1.0 7.06e+04 - 1.08e-02 3.88e-04f 1\n", + " 152 1.1027853e+05 5.52e+03 3.78e+05 -1.0 3.54e+04 - 1.88e-02 4.05e-06f 1\n", + " 153r 1.1027853e+05 5.52e+03 1.00e+03 3.7 0.00e+00 - 0.00e+00 2.03e-08R 2\n", + " 154r 1.1027886e+05 6.60e+02 2.29e+03 3.7 5.51e+06 - 3.42e-03 9.93e-04f 1\n", + " 155 1.0759473e+05 6.61e+02 2.40e+01 -1.0 1.36e+06 - 5.20e-03 2.07e-04f 1\n", + " 156 1.0758344e+05 6.61e+02 1.68e+05 -1.0 5.36e+05 - 1.38e-02 2.11e-06f 1\n", + " 157r 1.0758344e+05 6.61e+02 9.99e+02 2.8 0.00e+00 - 0.00e+00 1.06e-08R 2\n", + " 158r 1.0758424e+05 1.76e+02 9.97e+02 2.8 6.61e+05 - 1.95e-03 9.90e-04f 1\n", + " 159 1.0727225e+05 1.76e+02 2.26e+02 -1.0 1.28e+06 - 5.75e-03 2.52e-05f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 1.0727102e+05 1.76e+02 1.38e+07 -1.0 4.83e+05 - 1.54e-02 2.52e-07f 1\n", + " 161r 1.0727102e+05 1.76e+02 1.00e+03 2.2 0.00e+00 - 0.00e+00 2.10e-09R 2\n", + " 162r 1.0727100e+05 4.49e+01 3.89e+03 2.2 1.76e+05 - 3.33e-01 9.90e-04f 1\n", + " 163 1.0718953e+05 4.49e+01 8.71e+02 -1.0 1.28e+06 - 5.81e-03 6.62e-06f 1\n", + " 164 1.0718937e+05 4.49e+01 2.04e+08 -1.0 4.76e+05 - 1.56e-02 3.31e-08f 2\n", + " 165 1.0719074e+05 4.49e+01 2.41e+12 -1.0 1.39e+07 - 3.27e-04 2.74e-08H 1\n", + " 166r 1.0719074e+05 4.49e+01 1.00e+03 1.7 0.00e+00 - 0.00e+00 1.84e-11R 2\n", + " 167r 1.0719095e+05 1.12e+01 9.90e+02 1.7 4.49e+04 - 1.70e-01 9.90e-04f 1\n", + " 168 1.0717059e+05 1.12e+01 3.49e+03 -1.0 1.27e+06 - 5.83e-03 1.66e-06f 1\n", + " 169r 1.0717059e+05 1.12e+01 9.99e+02 1.0 0.00e+00 - 0.00e+00 8.30e-09R 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 1.0717179e+05 3.98e+00 9.97e+02 1.0 1.12e+04 - 7.26e-02 9.90e-04f 1\n", + " 171 1.0716685e+05 3.98e+00 1.42e+04 -1.0 1.24e+06 - 5.88e-03 4.11e-07f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 172r 1.0716685e+05 3.98e+00 9.99e+02 0.6 0.00e+00 - 0.00e+00 2.06e-09R 2\n", + " 173r 1.0716902e+05 1.22e+01 9.95e+02 0.6 3.98e+03 - 2.60e-02 9.90e-04f 1\n", + " 174r 1.0721151e+05 3.96e+03 9.71e+02 0.6 7.43e+02 - 5.48e-02 2.49e-02f 1\n", + " 175r 1.0733554e+05 8.77e+03 8.92e+02 0.6 7.42e+02 - 2.07e-01 7.93e-02f 1\n", + " 176r 1.0744861e+05 1.81e+04 3.21e+03 0.6 6.39e+02 - 2.76e-01 9.12e-02f 1\n", + " 177r 1.0760156e+05 1.26e+04 2.49e+03 0.6 4.84e+02 - 1.35e-01 1.57e-01f 1\n", + " 178r 1.0759534e+05 1.76e+04 3.00e+03 0.6 8.50e+01 - 2.93e-01 1.80e-01f 1\n", + " 179r 1.0769358e+05 1.54e+04 3.69e+03 0.6 5.91e+01 - 3.85e-01 2.13e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 1.0817736e+05 6.68e+03 3.86e+03 0.6 1.21e+02 - 9.01e-01 5.48e-01f 1\n", + " 181r 1.0810596e+05 6.25e+03 2.22e+03 0.6 6.69e+01 - 3.03e-01 3.61e-01f 1\n", + " 182r 1.0804719e+05 1.30e+03 4.59e+02 0.6 3.46e+01 - 9.90e-01 1.00e+00f 1\n", + " 183r 1.0811628e+05 1.96e+02 1.22e+01 0.6 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 1.0810982e+05 6.43e+00 3.18e+00 0.6 9.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 185r 1.0822116e+05 9.78e+02 1.36e+02 -0.8 6.25e+01 - 7.37e-01 6.38e-01f 1\n", + " 186r 1.1108726e+05 1.47e+03 9.49e+01 -0.8 1.17e+03 - 7.44e-01 5.74e-01f 1\n", + " 187r 1.1267097e+05 5.05e+03 8.55e+01 -0.8 5.95e+02 - 1.00e+00 7.56e-01f 1\n", + " 188r 1.1279724e+05 1.61e+03 1.89e+01 -0.8 1.03e+02 - 6.41e-01 6.99e-01h 1\n", + " 189r 1.1300124e+05 7.91e+01 5.00e-01 -0.8 6.37e+01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 1.1300781e+05 1.88e+00 3.19e-02 -0.8 9.42e-01 - 1.00e+00 1.00e+00h 1\n", + " 191r 1.1300781e+05 1.88e+00 9.99e+02 0.3 0.00e+00 - 0.00e+00 1.25e-09R 2\n", + " 192r 1.1300966e+05 4.83e-01 2.16e+04 0.3 1.88e+03 - 8.88e-02 9.90e-04f 1\n", + " 193r 1.1300966e+05 4.83e-01 9.99e+02 -0.3 0.00e+00 - 0.00e+00 1.49e-09R 2\n", + " 194r 1.1301306e+05 1.93e-01 1.24e+04 -0.3 8.04e+02 - 2.20e-01 9.90e-04f 1\n", + " 195r 1.1301306e+05 1.93e-01 9.99e+02 -0.7 0.00e+00 - 0.00e+00 1.56e-09R 2\n", + " 196r 1.1302132e+05 1.93e-01 2.17e+04 -0.7 1.31e+03 - 9.64e-01 1.54e-03f 1\n", + " 197r 1.1823161e+05 6.17e+02 4.80e+02 -0.7 1.34e+03 - 9.89e-01 9.61e-01f 1\n", + " 198r 1.1798536e+05 5.28e+02 6.49e+01 -0.7 5.91e+01 - 7.43e-01 1.00e+00h 1\n", + " 199r 1.1805718e+05 2.99e+02 3.87e+00 -0.7 1.29e+01 - 9.93e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 1.1805876e+05 8.10e+01 1.75e+00 -0.7 3.71e+00 - 1.00e+00 1.00e+00h 1\n", + " 201r 1.1806057e+05 5.70e-01 1.05e-03 -0.7 4.13e-01 - 1.00e+00 1.00e+00h 1\n", + " 202r 1.1811792e+05 3.68e+02 9.69e+00 -1.4 2.10e+01 - 9.31e-01 9.67e-01f 1\n", + " 203r 1.2050787e+05 7.67e+02 6.64e+01 -1.4 1.57e+03 - 6.63e-01 5.35e-01h 1\n", + " 204r 1.2249012e+05 4.59e+02 1.35e+02 -1.4 7.27e+02 - 6.94e-01 1.00e+00h 1\n", + " 205r 1.2248902e+05 6.11e+02 4.56e+01 -1.4 3.65e+00 - 1.00e+00 1.00e+00h 1\n", + " 206r 1.2249445e+05 1.16e+02 6.38e+00 -1.4 7.80e-01 - 1.00e+00 1.00e+00h 1\n", + " 207r 1.2249392e+05 1.06e+00 1.19e-01 -1.4 7.63e-02 - 1.00e+00 1.00e+00h 1\n", + " 208r 1.2249396e+05 1.76e-01 3.39e-05 -1.4 6.38e-03 - 1.00e+00 1.00e+00h 1\n", + " 209r 1.2253738e+05 1.27e+02 1.74e+01 -3.2 1.09e+01 - 9.28e-01 8.33e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 1.2342956e+05 2.40e+03 2.42e+02 -3.2 1.70e+04 - 4.06e-01 1.26e-01f 1\n", + " 211r 1.2343158e+05 2.40e+03 7.66e+02 -3.2 8.82e+03 - 2.08e-01 1.77e-04h 1\n", + " 212r 1.2680154e+05 2.07e+03 8.71e+02 -3.2 2.55e+03 - 3.91e-01 1.86e-01h 1\n", + " 213r 1.2680301e+05 2.06e+03 1.05e+03 -3.2 9.06e+01 - 7.96e-01 5.94e-03h 1\n", + " 214r 1.2694462e+05 1.25e+03 8.56e+02 -3.2 7.71e+01 - 1.00e+00 3.94e-01h 1\n", + " 215r 1.2716494e+05 2.37e+03 2.47e+02 -3.2 4.31e+01 - 1.00e+00 1.00e+00h 1\n", + " 216r 1.2716480e+05 3.75e+02 2.05e+02 -3.2 1.32e+00 - 8.45e-01 9.35e-01h 1\n", + " 217r 1.2716432e+05 2.49e+01 7.82e+01 -3.2 2.34e-01 - 1.00e+00 9.40e-01h 1\n", + " 218r 1.2716443e+05 1.57e+00 2.02e+00 -3.2 1.03e-01 - 1.00e+00 1.00e+00h 1\n", + " 219r 1.2716444e+05 1.72e-01 1.84e-02 -3.2 3.20e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220 1.2716441e+05 1.72e-01 5.84e+02 -1.0 3.35e+04 - 1.89e-04 1.11e-06f 3\n", + " 221 1.2716433e+05 1.72e-01 6.98e+03 -1.0 3.33e+04 - 5.76e-04 3.00e-06f 2\n", + " 222 1.2716001e+05 6.59e-01 6.09e+03 -1.0 3.26e+04 - 1.20e-04 1.53e-04f 1\n", + " 223 1.2715671e+05 9.98e-01 2.65e+04 -1.0 3.24e+04 - 8.81e-04 1.13e-04f 2\n", + " 224 1.2715642e+05 1.00e+00 3.99e+04 -1.0 3.21e+04 - 5.12e-04 1.02e-05f 8\n", + " 225 1.2715609e+05 1.00e+00 2.11e+05 -1.0 3.20e+04 - 6.44e-03 1.21e-05f 8\n", + " 226 1.2715594e+05 1.01e+00 2.22e+05 -1.0 3.12e+04 - 4.13e-04 7.29e-06f 9\n", + " 227 1.2715578e+05 1.01e+00 6.06e+05 -1.0 3.12e+04 - 1.45e-02 7.28e-06f 9\n", + " 228 1.2712455e+05 5.74e+01 5.61e+05 -1.0 2.98e+04 - 4.34e-04 2.11e-03f 1\n", + " 229 1.2712496e+05 5.76e+01 5.61e+05 -1.0 2.47e+04 - 1.73e-04 1.73e-04s 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230 1.2713698e+05 1.14e+02 5.59e+05 -1.0 2.41e+04 - 2.70e-03 2.70e-03s 10\n", + " 231r 1.2713698e+05 1.14e+02 1.00e+03 2.1 0.00e+00 - 0.00e+00 0.00e+00R 1\n", + " 232r 1.2716197e+05 1.69e+03 3.15e+04 2.1 1.14e+05 - 1.07e-05 2.61e-04f 1\n", + " 233r 1.2714570e+05 2.14e+03 2.94e+04 2.1 8.31e+04 - 5.38e-04 1.00e-03f 1\n", + " 234r 1.2714342e+05 2.61e+03 2.90e+04 2.1 1.04e+04 - 2.06e-03 1.77e-03f 1\n", + " 235r 1.2713596e+05 3.50e+03 2.84e+04 2.1 1.57e+03 - 3.35e-03 4.25e-03f 1\n", + " 236r 1.2708154e+05 5.65e+03 2.84e+04 2.1 7.55e+02 - 2.00e-03 1.09e-02f 1\n", + " 237r 1.2708154e+05 5.08e+03 2.48e+04 2.1 8.00e+00 2.0 2.43e-02 1.02e-01f 1\n", + " 238r 1.2708154e+05 4.85e+03 2.33e+04 2.1 8.06e+00 1.5 3.31e-01 4.61e-02f 1\n", + " 239r 1.2708156e+05 1.14e+04 2.24e+04 2.1 2.91e+02 1.0 8.89e-03 1.92e-02f 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 1.2708156e+05 3.64e+03 1.67e+03 2.1 3.56e-01 3.3 9.90e-01 9.24e-01f 1\n", + " 241r 1.2726934e+05 1.67e+04 1.27e+04 2.1 2.58e+02 - 4.63e-01 1.00e+00f 1\n", + " 242r 1.2736337e+05 1.24e+03 6.79e+01 2.1 2.54e+01 - 1.00e+00 1.00e+00f 1\n", + " 243r 1.2744147e+05 1.56e+03 1.20e+02 2.1 8.73e+01 - 1.00e+00 1.00e+00f 1\n", + " 244r 1.2739248e+05 1.69e+04 1.76e+02 2.1 4.12e+01 - 1.00e+00 1.00e+00f 1\n", + " 245r 1.2738697e+05 6.55e+02 5.20e+00 2.1 6.39e+00 - 1.00e+00 1.00e+00h 1\n", + " 246r 1.2749175e+05 1.38e+04 1.09e+03 1.4 1.60e+02 - 4.91e-01 7.12e-01f 1\n", + " 247r 1.2761275e+05 2.71e+03 4.74e+02 1.4 6.53e+01 - 6.43e-01 1.00e+00f 1\n", + " 248r 1.2750105e+05 1.80e+03 4.59e+01 1.4 3.96e+01 - 1.00e+00 1.00e+00f 1\n", + " 249r 1.2754311e+05 6.91e+01 1.63e+01 1.4 1.22e+01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 250r 1.2731384e+05 3.27e+03 7.52e+01 0.7 9.90e+01 - 9.32e-01 9.07e-01f 1\n", + " 251r 1.2733916e+05 3.31e+03 3.81e+02 0.7 2.94e+01 - 9.88e-01 1.00e+00f 1\n", + " 252r 1.2733916e+05 7.28e+00 2.53e+01 0.7 3.71e-02 2.8 1.00e+00 1.00e+00h 1\n", + " 253 1.2683674e+05 7.41e+03 1.23e+04 -1.0 3.89e+05 - 1.95e-04 3.22e-04f 1\n", + " 254 1.2676691e+05 7.46e+03 1.24e+04 -1.0 3.46e+05 - 8.15e-04 8.67e-05f 1\n", + " 255 1.2676634e+05 7.46e+03 1.25e+04 -1.0 3.35e+05 - 4.00e-06 1.86e-05f 1\n", + " 256r 1.2676634e+05 7.46e+03 9.99e+02 3.9 0.00e+00 - 0.00e+00 2.79e-07R 11\n", + " 257r 1.2676664e+05 6.95e+03 1.73e+03 3.9 7.46e+06 - 9.44e-06 6.75e-05f 1\n", + " 258r 1.2676749e+05 1.45e+04 4.19e+03 3.9 6.89e+06 - 5.87e-03 2.42e-04f 1\n", + " 259r 1.2677021e+05 2.06e+04 1.68e+05 3.9 7.68e+05 - 2.42e-01 6.81e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 260r 1.2676657e+05 1.54e+04 1.99e+04 3.2 2.06e+03 - 7.98e-01 2.46e-01f 1\n", + " 261r 1.2679614e+05 1.25e+05 6.11e+04 3.2 4.23e+02 - 6.64e-01 9.18e-01f 1\n", + " 262r 1.2679614e+05 1.06e+05 5.24e+04 3.2 2.15e+01 2.0 2.47e-01 1.50e-01h 1\n", + " 263r 1.2679699e+05 9.96e+04 4.99e+04 3.2 3.45e+02 - 1.19e-01 5.68e-02f 1\n", + " 264r 1.2667363e+05 3.90e+04 1.72e+04 3.2 9.75e+01 - 1.00e+00 9.82e-01f 1\n", + " 265r 1.2671998e+05 8.46e+04 5.46e+03 3.2 4.82e+01 - 9.57e-01 1.00e+00f 1\n", + " 266r 1.2672645e+05 3.56e+04 8.81e+03 3.2 3.41e+01 - 7.54e-01 5.00e-01f 2\n", + " 267r 1.2673515e+05 2.88e+04 2.96e+03 3.2 3.52e+01 - 8.41e-01 5.00e-01h 2\n", + " 268r 1.2674045e+05 2.96e+04 5.20e+02 3.2 1.42e+01 - 1.00e+00 1.00e+00h 1\n", + " 269r 1.2670264e+05 4.00e+04 1.89e+03 3.2 4.20e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 270r 1.2671520e+05 2.66e+04 2.95e+03 3.2 3.23e+01 - 1.00e+00 5.00e-01h 2\n", + " 271r 1.2674449e+05 1.92e+04 6.30e+02 3.2 3.26e+01 - 1.00e+00 1.00e+00h 1\n", + " 272r 1.2667937e+05 1.21e+04 1.31e+03 3.2 4.68e+01 - 8.60e-01 8.81e-01H 1\n", + " 273r 1.2675843e+05 1.14e+05 1.38e+03 2.5 2.14e+02 - 9.15e-01 9.58e-01f 1\n", + " 274r 1.2689727e+05 2.02e+04 6.57e+02 2.5 1.53e+02 - 8.86e-01 9.29e-01f 1\n", + " 275r 1.2682834e+05 4.79e+03 1.01e+03 2.5 8.87e+01 - 1.29e-01 1.00e+00f 1\n", + " 276r 1.2683302e+05 7.29e+03 2.75e+01 2.5 1.48e+01 - 1.00e+00 1.00e+00f 1\n", + " 277r 1.2683771e+05 1.69e+02 2.08e+00 2.5 2.17e+00 - 1.00e+00 1.00e+00h 1\n", + " 278 9.8178178e+04 4.74e+03 3.17e+02 -1.0 1.14e+06 - 4.18e-03 3.73e-03f 1\n", + " 279 9.7892691e+04 4.74e+03 4.16e+02 -1.0 3.14e+05 - 1.05e-02 8.44e-05f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 280 9.7891957e+04 4.74e+03 6.56e+06 -1.0 9.57e+04 - 1.40e-02 8.51e-07f 1\n", + " 281 9.7890561e+04 4.74e+03 1.74e+11 -1.0 2.12e+07 - 2.28e-04 8.51e-09f 1\n", + " 282 8.8769650e+04 4.74e+03 7.10e+11 -1.0 7.63e+07 - 7.92e-05 1.93e-05f 1\n", + " 283r 8.8769650e+04 4.74e+03 1.00e+03 3.7 0.00e+00 - 0.00e+00 7.21e-12R 2\n", + " 284r 8.8769664e+04 3.34e+03 2.82e+04 3.7 4.74e+06 - 5.33e-02 2.94e-04f 1\n", + " 285 8.8693654e+04 3.34e+03 3.82e+02 -1.0 1.57e+05 - 1.43e-04 4.15e-05f 1\n", + " 286 8.8692951e+04 3.34e+03 2.28e+03 -1.0 1.43e+05 - 2.18e-04 4.17e-07f 1\n", + " 287r 8.8692951e+04 3.34e+03 9.99e+02 3.5 0.00e+00 - 0.00e+00 2.08e-09R 2\n", + " 288r 8.8692949e+04 3.30e+03 4.79e+03 3.5 3.34e+06 - 1.41e-03 1.30e-05f 1\n", + " 289r 8.8693153e+04 5.46e+02 4.17e+04 3.5 1.37e+06 - 1.36e-01 2.38e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 290 8.7457681e+04 5.52e+02 9.15e+02 -1.0 3.59e+05 - 1.38e-02 3.41e-04f 1\n", + " 291 8.7456415e+04 5.52e+02 4.84e+06 -1.0 5.31e+04 - 1.82e-02 3.49e-06f 1\n", + " 292r 8.7456415e+04 5.52e+02 1.00e+03 2.7 0.00e+00 - 0.00e+00 1.76e-08R 2\n", + " 293r 8.7456389e+04 1.39e+02 2.42e+04 2.7 5.52e+05 - 4.97e-01 9.90e-04f 1\n", + " 294 8.7370462e+04 1.39e+02 5.88e+02 -1.0 3.62e+05 - 1.40e-02 2.36e-05f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 295r 8.7370462e+04 1.39e+02 9.99e+02 2.1 0.00e+00 - 0.00e+00 1.18e-07R 2\n", + " 296r 8.7370048e+04 3.52e+01 3.53e+03 2.1 1.39e+05 - 2.88e-01 9.90e-04f 1\n", + " 297 8.7365867e+04 3.52e+01 8.57e+03 -1.0 5.17e+04 - 1.49e-02 1.02e-05f 1\n", + " 298r 8.7365867e+04 3.52e+01 1.00e+03 1.5 0.00e+00 - 0.00e+00 5.08e-08R 2\n", + " 299r 8.7366392e+04 9.28e+00 9.94e+02 1.5 3.52e+04 - 2.03e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 300 8.7366287e+04 9.28e+00 8.33e+05 -1.0 7.00e+04 - 1.52e-02 7.75e-07f 2\n", + " 301r 8.7366287e+04 9.28e+00 1.00e+03 1.0 0.00e+00 - 0.00e+00 3.92e-07R 2\n", + " 302r 8.7367439e+04 1.24e+01 1.01e+03 1.0 9.28e+03 - 3.08e-02 9.90e-04f 1\n", + " 303r 8.7397075e+04 3.59e+03 9.77e+02 1.0 3.75e+02 - 1.00e-01 2.88e-02f 1\n", + " 304r 8.7438378e+04 3.48e+03 9.08e+02 1.0 3.31e+02 - 8.91e-02 4.71e-02f 1\n", + " 305r 8.7508053e+04 5.97e+03 1.50e+03 1.0 2.88e+02 - 4.19e-01 8.34e-02f 1\n", + " 306r 8.7712845e+04 2.48e+04 3.57e+03 1.0 2.81e+02 - 8.23e-01 3.25e-01f 1\n", + " 307r 8.7793008e+04 1.34e+04 2.30e+03 1.0 5.17e+01 - 4.78e-01 4.32e-01f 1\n", + " 308r 8.7846425e+04 7.72e+03 1.02e+03 1.0 2.62e+01 - 7.14e-01 6.69e-01f 1\n", + " 309r 8.7909231e+04 2.83e+03 4.55e+03 1.0 2.21e+01 - 9.91e-01 6.64e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 310r 8.7935450e+04 1.38e+03 2.75e+03 1.0 1.16e+01 - 6.88e-01 5.11e-01f 1\n", + " 311r 8.7934743e+04 7.89e+01 4.04e+02 1.0 5.65e+00 - 1.00e+00 1.00e+00f 1\n", + " 312r 8.7774627e+04 2.97e+03 1.68e+02 0.3 4.16e+01 - 9.23e-01 9.88e-01f 1\n", + " 313r 8.8807837e+04 4.00e+03 1.24e+01 0.3 1.93e+02 - 1.00e+00 1.00e+00h 1\n", + " 314r 8.8874130e+04 2.92e+02 1.89e+00 0.3 9.71e+00 - 1.00e+00 1.00e+00h 1\n", + " 315r 8.8879501e+04 1.07e+00 1.78e-02 0.3 1.06e+00 - 1.00e+00 1.00e+00h 1\n", + " 316r 8.8879501e+04 1.07e+00 9.99e+02 0.0 0.00e+00 - 0.00e+00 2.69e-07R 2\n", + " 317r 8.8881473e+04 2.72e-01 1.76e+04 0.0 1.07e+03 - 9.21e-01 9.90e-04f 1\n", + " 318r 8.8881473e+04 2.72e-01 9.99e+02 -0.6 0.00e+00 - 0.00e+00 2.66e-07R 2\n", + " 319r 8.8884807e+04 2.82e-01 1.14e+03 -0.6 7.03e+02 - 2.34e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 320r 8.9636313e+04 9.61e+02 5.59e+03 -0.6 8.27e+02 - 8.63e-01 1.73e-01f 1\n", + " 321r 9.0993769e+04 1.08e+03 5.48e+03 -0.6 7.71e+02 - 5.54e-01 3.35e-01f 1\n", + " 322r 9.2474307e+04 2.15e+03 5.68e+03 -0.6 4.81e+02 - 8.60e-01 5.30e-01f 1\n", + " 323r 9.3478773e+04 1.06e+03 1.62e+03 -0.6 1.77e+02 - 9.90e-01 8.80e-01h 1\n", + " 324r 9.3554925e+04 1.01e+02 2.92e+01 -0.6 1.84e+01 - 9.96e-01 1.00e+00h 1\n", + " 325r 9.3556224e+04 1.65e-01 1.08e-02 -0.6 2.08e-01 - 1.00e+00 1.00e+00h 1\n", + " 326r 9.3556224e+04 1.65e-01 9.99e+02 -0.8 0.00e+00 - 0.00e+00 2.98e-10R 2\n", + " 327r 9.3571208e+04 1.65e-01 1.76e+04 -0.8 9.65e+02 - 8.70e-01 2.51e-03f 1\n", + " 328r 9.8897161e+04 1.50e+03 3.13e+03 -0.8 1.01e+03 - 9.59e-01 8.71e-01f 1\n", + " 329r 9.8336345e+04 5.99e+01 1.09e+02 -0.8 7.97e+01 - 9.90e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 330r 9.8338262e+04 4.49e-01 4.27e-01 -0.8 3.37e+00 - 9.95e-01 1.00e+00h 1\n", + " 331r 9.8363923e+04 2.98e+02 1.32e+02 -1.5 9.78e+00 - 1.00e+00 9.63e-01f 1\n", + " 332r 1.0078662e+05 2.43e+02 1.46e+02 -1.5 6.27e+02 - 1.00e+00 6.63e-01h 1\n", + " 333r 1.0169690e+05 9.17e+01 9.25e+01 -1.5 1.53e+02 - 1.00e+00 7.05e-01h 1\n", + " 334r 1.0207081e+05 2.83e+00 2.90e+00 -1.5 3.21e+01 - 1.00e+00 1.00e+00h 1\n", + " 335r 1.0207272e+05 1.92e-01 6.60e-02 -1.5 8.17e+00 - 1.00e+00 1.00e+00h 1\n", + " 336r 1.0210277e+05 2.14e+02 1.11e+02 -2.2 5.08e+00 - 1.00e+00 9.77e-01f 1\n", + " 337r 1.0356247e+05 1.01e+03 5.29e+02 -2.2 5.28e+02 - 4.61e-01 2.44e-01h 1\n", + " 338r 1.0508487e+05 2.49e+03 4.03e+03 -2.2 3.97e+02 - 1.00e+00 3.31e-01h 1\n", + " 339r 1.0815887e+05 1.05e+03 6.46e+02 -2.2 2.67e+02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 340r 1.0790832e+05 9.75e+01 1.58e+01 -2.2 2.29e+01 - 1.00e+00 1.00e+00h 1\n", + " 341r 1.0799170e+05 2.00e+01 1.12e+00 -2.2 7.74e+00 - 1.00e+00 1.00e+00h 1\n", + " 342r 1.0799969e+05 1.96e-01 1.83e-02 -2.2 7.42e-01 - 1.00e+00 1.00e+00h 1\n", + " 343r 1.0799977e+05 1.96e-01 1.39e-06 -2.2 6.97e-03 - 1.00e+00 1.00e+00h 1\n", + " 344r 1.0810014e+05 1.22e+00 2.91e+02 -5.0 2.10e+01 - 8.95e-01 4.72e-01f 1\n", + " 345r 1.0810406e+05 4.81e+00 2.50e+02 -5.0 8.05e-01 -2.0 3.48e-01 4.35e-01h 1\n", + " 346r 1.0823331e+05 4.73e+00 3.13e+02 -5.0 6.45e+03 - 2.53e-01 1.89e-02f 1\n", + " 347r 1.0723140e+05 1.69e+02 4.34e+02 -5.0 1.58e+03 - 3.99e-03 4.40e-01h 1\n", + " 348r 1.0742343e+05 1.63e+02 3.79e+02 -5.0 1.51e+03 - 6.57e-01 6.72e-02h 1\n", + " 349r 1.0834320e+05 2.55e+02 5.98e+02 -5.0 1.45e+03 - 1.56e-01 3.47e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 350r 1.0905675e+05 4.18e+02 9.23e+02 -5.0 1.03e+03 - 2.62e-02 7.65e-01h 1\n", + " 351r 1.1388747e+05 2.64e+03 2.51e+03 -5.0 1.45e+03 - 2.53e-01 6.38e-01h 1\n", + " 352r 1.1388763e+05 1.74e+03 4.40e+03 -5.0 7.03e-01 -2.5 8.02e-01 3.41e-01h 1\n", + " 353r 1.1388766e+05 1.73e+03 6.62e+03 -5.0 5.05e-01 -3.0 9.72e-01 9.80e-03h 1\n", + " 354r 1.1417543e+05 1.41e+03 5.38e+03 -5.0 7.36e+02 - 4.04e-02 1.84e-01h 1\n", + " 355r 1.1417550e+05 1.40e+03 5.61e+03 -5.0 1.38e+00 -3.4 1.00e+00 3.66e-03h 1\n", + " 356r 1.1550772e+05 4.07e+02 1.18e+03 -5.0 7.26e+02 - 4.25e-02 8.35e-01h 1\n", + " 357r 1.1552641e+05 2.23e+02 7.45e+02 -5.0 4.56e+00 -3.9 6.30e-01 4.52e-01h 1\n", + " 358r 1.1558163e+05 1.25e+02 4.23e+02 -5.0 1.37e+01 -4.4 9.96e-02 4.40e-01h 1\n", + " 359r 1.1577336e+05 1.09e+02 5.76e+02 -5.0 4.44e+01 -4.9 7.36e-02 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 360r 1.1577561e+05 2.45e+03 5.78e+02 -5.0 7.08e+00 -2.6 1.51e-01 1.00e+00h 1\n", + " 361r 1.1577726e+05 1.89e+03 2.65e+02 -5.0 4.00e+00 -3.1 7.58e-01 2.50e-01h 3\n", + " 362r 1.1578214e+05 1.53e+03 1.98e+02 -5.0 5.80e+00 -3.6 3.32e-01 2.50e-01h 3\n", + " 363r 1.1578330e+05 1.50e+03 1.65e+02 -5.0 8.12e+00 -4.1 1.00e+00 2.01e-02h 6\n", + " 364r 1.1578639e+05 1.48e+03 1.42e+02 -5.0 1.72e+01 -4.5 4.68e-01 1.80e-02h 6\n", + " 365r 1.1592763e+05 1.40e+03 1.17e+02 -5.0 5.18e+01 -5.0 5.33e-01 2.75e-01h 2\n", + " 366r 1.1617094e+05 1.53e+03 9.71e+01 -5.0 1.50e+02 -5.5 1.75e-01 1.67e-01h 1\n", + " 367r 1.1703261e+05 1.26e+03 8.04e+01 -5.0 5.54e+02 -6.0 3.66e-01 1.80e-01h 1\n", + " 368r 1.2972938e+05 4.18e+03 1.66e+02 -5.0 2.79e+03 -6.4 2.07e-01 7.16e-01h 1\n", + " 369r 1.2972954e+05 4.18e+03 3.20e+02 -5.0 8.11e+02 -6.0 3.98e-01 3.44e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 370r 1.2975480e+05 4.04e+03 5.38e+02 -5.0 1.31e+02 -3.8 1.19e-02 3.23e-02h 1\n", + " 371r 1.2964740e+05 3.38e+03 4.90e+02 -5.0 1.09e+02 -4.3 1.67e-03 1.64e-01h 1\n", + " 372r 1.2966158e+05 2.40e+03 3.46e+02 -5.0 7.46e+00 -3.8 2.68e-01 2.91e-01h 1\n", + " 373r 1.2973030e+05 1.27e+03 1.84e+02 -5.0 2.25e+01 -4.3 1.00e+00 4.68e-01h 1\n", + " 374r 1.3017019e+05 5.33e+01 4.05e+02 -5.0 6.82e+01 -4.8 3.63e-01 1.00e+00h 1\n", + " 375r 1.3028200e+05 5.05e+01 3.67e+02 -5.0 2.24e+02 -5.3 1.06e-01 7.97e-02h 1\n", + " 376r 1.3069758e+05 4.92e+01 3.93e+02 -5.0 8.09e+02 -5.7 4.51e-02 7.81e-02h 1\n", + " 377r 1.3069758e+05 4.92e+01 3.90e+02 -5.0 2.98e+03 - 1.65e-02 3.13e-05h 7\n", + " 378r 1.3069919e+05 4.92e+01 4.31e+02 -5.0 1.68e+03 - 1.08e-01 3.30e-04h 5\n", + " 379r 1.3126228e+05 4.78e+01 4.36e+02 -5.0 9.27e+02 - 1.70e-01 7.48e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 380r 1.3306851e+05 3.73e+01 4.13e+02 -5.0 9.00e+02 - 4.51e-01 2.48e-01h 1\n", + " 381r 1.3831309e+05 1.63e+02 4.11e+02 -5.0 6.80e+02 - 1.96e-01 9.55e-01h 1\n", + " 382r 1.3831686e+05 1.59e+02 4.88e+02 -5.0 2.62e+01 - 1.36e-02 2.42e-02h 1\n", + " 383r 1.3854324e+05 2.37e+01 6.34e+02 -5.0 2.99e+01 - 3.17e-01 9.37e-01H 1\n", + " 384r 1.3854435e+05 2.30e+01 5.98e+02 -5.0 1.92e+01 - 3.14e-02 6.34e-02h 1\n", + " 385r 1.3855788e+05 1.90e+02 3.37e+02 -5.0 1.61e+01 - 6.68e-01 1.00e+00h 1\n", + " 386r 1.3855814e+05 3.75e+00 1.12e+01 -5.0 9.39e-02 - 9.55e-01 1.00e+00h 1\n", + " 387r 1.3855815e+05 4.13e+00 6.63e+02 -5.0 1.20e+00 - 3.35e-01 1.68e-01H 1\n", + " 388r 1.3855831e+05 1.34e+02 1.92e+01 -5.0 8.03e-01 - 1.00e+00 1.00e+00h 1\n", + " 389r 1.3855837e+05 9.15e+00 1.46e+00 -5.0 1.61e-01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 390r 1.3855836e+05 2.45e-01 1.28e+00 -5.0 2.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 391r 1.3855836e+05 2.45e-01 3.53e-02 -5.0 1.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 392r 1.3855836e+05 2.45e-01 1.21e-06 -5.0 2.41e-05 - 1.00e+00 1.00e+00h 1\n", + " 393r 1.3855744e+05 2.08e+01 5.23e+02 -7.5 5.05e-01 - 8.64e-01 7.40e-01f 1\n", + " 394r 1.3855744e+05 1.51e+01 9.25e+02 -7.5 1.29e+00 - 2.87e-01 3.84e-01h 1\n", + " 395r 1.3855750e+05 8.64e+00 8.72e+02 -7.5 6.46e-01 - 4.26e-01 4.61e-01h 1\n", + " 396r 1.3855752e+05 4.84e+00 4.49e+02 -7.5 3.22e-01 - 6.28e-01 6.53e-01h 1\n", + " 397r 1.3855749e+05 3.20e+00 4.97e+02 -7.5 1.50e-01 - 2.97e-01 4.40e-01h 1\n", + " 398r 1.3855747e+05 1.96e+00 6.90e+02 -7.5 3.00e-02 -2.6 4.68e-02 3.88e-01h 1\n", + " 399r 1.3855745e+05 5.42e-01 5.37e+02 -7.5 2.62e-02 -3.1 3.97e-01 7.24e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 400r 1.3855744e+05 4.46e-01 3.86e+02 -7.5 2.77e-02 -2.7 2.69e-01 1.80e-01h 1\n", + " 401r 1.3855744e+05 4.34e-01 5.63e+02 -7.5 1.66e-01 -3.1 2.98e-01 2.76e-02h 1\n", + " 402r 1.3855738e+05 4.70e+00 6.16e+02 -7.5 6.32e-01 - 1.00e+00 2.87e-01h 1\n", + " 403r 1.3855735e+05 5.14e+00 3.38e+02 -7.5 3.82e-01 - 1.00e+00 2.07e-01h 1\n", + " 404r 1.3855722e+05 1.35e+01 1.78e+00 -7.5 2.46e-01 - 1.00e+00 1.00e+00h 1\n", + " 405r 1.3855722e+05 2.45e-01 1.38e-02 -7.5 1.58e-02 - 1.00e+00 1.00e+00h 1\n", + " 406r 1.3855722e+05 2.45e-01 2.29e-04 -7.5 3.59e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 406\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 1.3855721777671148e+05 1.3855721777671148e+05\n", + "Dual infeasibility......: 6.9379110321402369e+00 6.9379110321402369e+00\n", + "Constraint violation....: 2.4525985132130276e-01 2.4525985132130276e-01\n", + "Complementarity.........: 3.1231128787715433e-08 3.1231128787715433e-08\n", + "Overall NLP error.......: 6.9379110321402369e+00 6.9379110321402369e+00\n", + "\n", + "\n", + "Number of objective function evaluations = 723\n", + "Number of objective gradient evaluations = 182\n", + "Number of equality constraint evaluations = 723\n", + "Number of inequality constraint evaluations = 723\n", + "Number of equality constraint Jacobian evaluations = 446\n", + "Number of inequality constraint Jacobian evaluations = 446\n", + "Number of Lagrangian Hessian evaluations = 407\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.635\n", + "Total CPU secs in NLP function evaluations = 0.068\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 138557.21777671148\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -0.0040595 : watt : False : (None, None)\n", + " Pressure Change : -2.4174e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 4.8078e-08 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 0.91034 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.089660 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.95213 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.041932 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.0029849 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.0029553 - - \n", + " Temperature kelvin 432.09 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 8.7385e-09 \n", + " flow_mol_phase Vap mole / second - 1.0000e-12 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.67175 0.67175 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.32825 0.32825 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.47214 0.47214 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.085798 0.085798 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.22083 0.22083 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.22124 0.22124 \n", + " temperature kelvin - 344.53 344.53 \n", + " pressure pascal - 1.0826e+05 1.0826e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8462216452944548\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -36576. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 0.17702 - - \n", + " Total Molar Flowrate Vap mole / second 0.068244 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 1.1730e-07 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 2.4279e-07 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 1.0000e-20 - - \n", + " Temperature kelvin 800.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 4.8078e-08 \n", + " flow_mol_phase Vap mole / second - 1.0000e-12 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.91034 0.91034 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.089660 0.089660 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.95213 0.95213 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.041932 0.041932 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.0029849 0.0029849 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.0029553 0.0029553 \n", + " temperature kelvin - 432.09 432.09 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 800.000 K\n", + "\n", + "F101 outlet temperature = 432.088 K\n", + "\n", + "F102 outlet temperature = 344.531 K\n", + "F102 outlet pressure = 108260.028 Pa\n", + "\n" + ] + } + ], + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 6040564f..e8169a6a 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1,2505 +1,2980 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 56db9c65..5f2b6695 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1,2869 +1,3243 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 6369d0f7..471da278 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1,2713 +1,3122 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.810084Z", - "start_time": "2025-06-26T20:17:04.786754Z" - } - }, - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 29" - ], - "outputs": [], - "execution_count": 29 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.104838Z", - "start_time": "2025-06-26T20:17:05.080097Z" - } - }, - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 0" - ], - "outputs": [], - "execution_count": 40 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.713878Z", - "start_time": "2025-06-26T20:17:07.711084Z" - } - }, - "source": [ - "# Check solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ], - "outputs": [], - "execution_count": 57 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.014719Z", - "start_time": "2025-06-26T20:17:07.926032Z" - } - }, - "source": [ - "import pytest\n", - "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ], - "outputs": [], - "execution_count": 61 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.063578Z", - "start_time": "2025-06-26T20:17:08.060157Z" - } - }, - "source": [ - "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ], - "outputs": [], - "execution_count": 63 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.275146Z", - "start_time": "2025-06-26T20:17:08.249526Z" - } - }, - "source": [ - "assert degrees_of_freedom(m) == 5" - ], - "outputs": [], - "execution_count": 69 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.683743Z", - "start_time": "2025-06-26T20:17:08.679403Z" - } - }, - "source": [ - "# Check for solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ], - "outputs": [], - "execution_count": 79 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.756874Z", - "start_time": "2025-06-26T20:17:08.753678Z" - } - }, - "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", - "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ], - "outputs": [], - "execution_count": 81 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.825473Z", - "start_time": "2025-06-26T20:17:08.820372Z" - } - }, - "source": [ - "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ], - "outputs": [], - "execution_count": 83 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.409008Z", + "start_time": "2025-11-20T21:46:10.382157Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 29" + ], + "outputs": [], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.568992Z", + "start_time": "2025-11-20T21:46:10.542995Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 0" + ], + "outputs": [], + "execution_count": 39 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.393870Z", + "start_time": "2025-11-20T21:46:17.390132Z" + } + }, + "source": [ + "# Check solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.571498Z", + "start_time": "2025-11-20T21:46:17.493194Z" + } + }, + "source": [ + "import pytest\n", + "\n", + "assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3)" + ], + "outputs": [], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.619054Z", + "start_time": "2025-11-20T21:46:17.613393Z" + } + }, + "source": [ + "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" + ], + "outputs": [], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.759351Z", + "start_time": "2025-11-20T21:46:17.728327Z" + } + }, + "source": [ + "assert degrees_of_freedom(m) == 5" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.045752Z", + "start_time": "2025-11-20T21:46:18.041549Z" + } + }, + "source": [ + "# Check for solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.093619Z", + "start_time": "2025-11-20T21:46:18.090039Z" + } + }, + "source": [ + "assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3)\n", + "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" + ], + "outputs": [], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:19.262061Z", + "start_time": "2025-11-20T21:46:18.121920Z" + } + }, + "source": [ + "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", + "print(value(m.fs.R101.outlet.temperature[0]))\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "763.5072359720118\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAssertionError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[82]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.H101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m500\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m763.484\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F101.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m301.881\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 5\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F102.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m362.935\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n", + "\u001b[31mAssertionError\u001b[39m: " + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 56db9c65..5f2b6695 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1,2869 +1,3243 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/initializing_testing.py b/idaes_examples/notebooks/docs/tut/core/initializing_testing.py new file mode 100644 index 00000000..673ccac9 --- /dev/null +++ b/idaes_examples/notebooks/docs/tut/core/initializing_testing.py @@ -0,0 +1,107 @@ +# Import required packages +from idaes.models_extra.power_generation.properties.natural_gas_PR import get_prop +from pyomo.environ import ( + ConcreteModel, + SolverFactory, + value, + units, + TransformationFactory, + Expression, +) +from idaes.core import FlowsheetBlock +from idaes.core.util.initialization import propagate_state +import idaes.logger as idaeslog +from idaes.models.properties import iapws95 +from idaes.models.unit_models import Feed +from idaes.models.unit_models.heater import Heater +from idaes.models.unit_models.heat_exchanger import ( + HeatExchanger, + delta_temperature_amtd_callback, +) +from pyomo.network import Arc, SequentialDecomposition +from idaes.core.util.model_statistics import degrees_of_freedom + +# Create the ConcreteModel and the FlowsheetBlock, and attach the flowsheet block to it. +m = ConcreteModel() + +m.fs = FlowsheetBlock(dynamic=False) + +m.fs.properties = iapws95.Iapws95ParameterBlock() + +m.fs.feed = Feed(property_package=m.fs.properties) +m.fs.heater = Heater(property_package=m.fs.properties) +m.fs.heat_exchanger = HeatExchanger( + delta_temperature_callback=delta_temperature_amtd_callback, + hot_side_name="shell", + cold_side_name="tube", + shell={"property_package": m.fs.properties}, + tube={"property_package": m.fs.properties}, +) + +m.fs.s01 = Arc(source=m.fs.feed.outlet, destination=m.fs.heat_exchanger.cold_side_inlet) +m.fs.s02 = Arc( + source=m.fs.heat_exchanger.cold_side_outlet, destination=m.fs.heater.inlet +) +m.fs.s03 = Arc( + source=m.fs.heater.outlet, destination=m.fs.heat_exchanger.hot_side_inlet +) + +TransformationFactory("network.expand_arcs").apply_to(m) +DOF_initial = degrees_of_freedom(m) +print("The initial DOF is {0}".format(DOF_initial)) + +# Fix the stream inlet conditions +m.fs.feed.flow_mol[0].fix(100) # mol/s +m.fs.feed.pressure[0].fix(101325) # Pa +m.fs.feed.enth_mol[0].fix(value(iapws95.htpx(T=293 * units.K, P=101325 * units.Pa))) + + +m.fs.heat_exchanger.overall_heat_transfer_coefficient[0].fix(500) # W/m2/K +m.fs.heat_exchanger.area.fix(50) + + +m.fs.heater.outlet.enth_mol.fix( + value(iapws95.htpx(T=1073 * units.K, P=101325 * units.Pa)) +) + +DOF_initial = degrees_of_freedom(m) +print("The DOF is {0}".format(DOF_initial)) + +# Provide initial guess for the shell inlet and create tear stream +m.fs.heat_exchanger.shell_inlet.flow_mol.fix(100) # mol/s +m.fs.heat_exchanger.shell_inlet.enth_mol[0].fix( + value(iapws95.htpx(T=1073 * units.K, P=101325 * 1.5 * units.Pa)) +) +m.fs.heat_exchanger.shell_inlet.pressure[0].fix(101325) # Pa +m.fs.s03_expanded.deactivate() + +DOF_initial = degrees_of_freedom(m) +print("The DOF is {0} after creating tear stream".format(DOF_initial)) + +m.fs.report() + +m.fs.feed.initialize(outlvl=idaeslog.INFO) +propagate_state(m.fs.s01) +m.fs.report() +m.fs.heat_exchanger.initialize(outlvl=idaeslog.INFO) +propagate_state(m.fs.s02) +m.fs.report() +m.fs.heater.initialize(outlvl=idaeslog.INFO) + +m.fs.report() + +# Solve the model +from idaes.core.solvers import get_solver + +solver = get_solver() +results = solver.solve(m, tee=False) + +# Reactivate tear stream, and unfix shell side initial conditions +m.fs.heat_exchanger.shell_inlet.flow_mol.unfix() +m.fs.heat_exchanger.shell_inlet.enth_mol[0].unfix() +m.fs.heat_exchanger.shell_inlet.pressure[0].unfix() +m.fs.s03_expanded.activate() + +results = solver.solve(m, tee=False) + +m.fs.report() From 91d17a45a6c4758b1167a19c869237e107006d5d Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 12 Jun 2025 16:23:37 -0600 Subject: [PATCH 28/36] Flash Unite and HDA Flowsheet Tutorial Revisions to reflect changes to initialization and scaling --- .../notebooks/docs/tut/core/flash_unit.ipynb | 1584 +++++- .../docs/tut/core/flash_unit_doc.ipynb | 3412 ++++++------- .../docs/tut/core/flash_unit_exercise.ipynb | 731 ++- .../docs/tut/core/flash_unit_solution.ipynb | 1536 +++++- .../docs/tut/core/flash_unit_test.ipynb | 1324 ++++- .../docs/tut/core/flash_unit_usr.ipynb | 1536 +++++- .../docs/tut/core/hda_flowsheet.ipynb | 2405 +++++++-- .../docs/tut/core/hda_flowsheet_doc.ipynb | 4057 ++++++++++----- .../tut/core/hda_flowsheet_exercise.ipynb | 4038 ++++++++++----- .../tut/core/hda_flowsheet_solution.ipynb | 4522 +++++++++++------ .../docs/tut/core/hda_flowsheet_test.ipynb | 4362 ++++++++++------ .../docs/tut/core/hda_flowsheet_usr.ipynb | 4522 +++++++++++------ 12 files changed, 23651 insertions(+), 10378 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index 6dc88109..2fe01927 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,50 +527,70 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "code", - "execution_count": 13, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.334804Z", + "start_time": "2025-06-06T16:45:50.327991Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 7" - ] + ], + "outputs": [], + "execution_count": 19 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -373,7 +627,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -381,30 +645,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -416,11 +686,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -429,93 +713,161 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "code", - "execution_count": 18, "metadata": { "tags": [ "testing" ] }, + "cell_type": "code", "outputs": [], + "execution_count": 24, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -523,58 +875,140 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "code", - "execution_count": 23, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.975773Z", + "start_time": "2025-06-06T17:04:32.972754Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ - "# Check for optimal solution\n", + "# Check for an optimal solution\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert status.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 38 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -594,10 +1028,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -607,38 +1044,95 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "code", - "execution_count": 26, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:39.229802Z", + "start_time": "2025-06-06T17:04:39.132903Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check optimal solution values\n", "import pytest\n", @@ -662,13 +1156,15 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(368, abs=1e-3)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 41 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -680,22 +1176,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -703,14 +1212,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -723,22 +1230,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -746,7 +1253,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -754,18 +1261,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -778,7 +1288,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -809,11 +1319,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -822,27 +1565,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -875,18 +1618,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -894,14 +1866,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -917,17 +1891,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -946,17 +2021,110 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check for solver status\n", "assert status.solver.termination_condition == TerminationCondition.optimal\n", @@ -981,7 +2149,9 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(369.07, abs=1e-2)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": null } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 9432ccbe..5f3b9777 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -1,1912 +1,1590 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Flash Unit Model\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", - "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", - "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", - "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", - "\n", - "## Key links to documentation\n", - "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", - "\n", - "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", - "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to perform the imports. Let a workshop organizer know if you see any errors.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", - "from idaes.core import FlowsheetBlock\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to create the objects\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Use the pprint method on the model, i.e. m.pprint(), to see what is currently contained in the model.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 Block Declarations\n", - " fs : Size=1, Index=None, Active=True\n", - " 1 Set Declarations\n", - " _time : Size=1, Index=None, Ordered=Insertion\n", - " Key : Dimen : Domain : Size : Members\n", - " None : 1 : Any : 1 : {0.0,}\n", - "\n", - " 1 Declarations: _time\n", - "\n", - "1 Declarations: fs\n" - ] - } - ], - "source": [ - "# Todo: call pprint on the model\n", - "m.pprint()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define Properties\n", - "\n", - "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", - "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", - "\n", - "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the following two cells to import and create the properties block.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", - " BTXParameterBlock,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.properties = BTXParameterBlock(\n", - " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Flash Unit\n", - "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", - "\n", - "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", - "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", - "\n", - "Some of the IDAES pre-written unit models:\n", - "* Mixer / Splitter\n", - "* Heater / Cooler\n", - "* Heat Exchangers (simple and 1D discretized)\n", - "* Flash\n", - "* Reactors (kinetic, equilibrium, gibbs, stoichiometric conversion)\n", - "* Pressure changing equipment (compressors, expanders, pumps)\n", - "* Feed and Product (source / sink) components\n", - "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the following two cells to import the Flash and create an instance of the unit model, attaching it to the flowsheet object.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Set Operating Conditions\n", - "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", - "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", - "\n", - "degrees_of_freedom(block)\n", - " Method to return the degrees of freedom of a model.\n", - " \n", - " Args:\n", - " block : model to be studied\n", - " \n", - " Returns:\n", - " Number of degrees of freedom in block.\n", - "\n" - ] - } - ], - "source": [ - "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Todo: Call the python help on the degrees_of_freedom function\n", - "help(degrees_of_freedom)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now print the degrees of freedom for your model. The result should be 7.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Degrees of Freedom = 7\n" - ] - } - ], - "source": [ - "# Todo: print the degrees of freedom for your model\n", - "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", - "\n", - "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", - "\n", - "As an example, to fix the molar flow of the inlet to be 1.0, you can use the following notation:\n", - "```python\n", - "m.fs.flash.inlet.flow_mol.fix(1.0)\n", - "```\n", - "\n", - "To specify variables that are indexed by components, you can use the following notation:\n", - "```python\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", - "```\n", - "\n", - "
\n", - "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", - "
\n", - "\n", - "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", - "\n", - "\n", - "To specify the value of a variable on the unit itself, use the following notation.\n", - "\n", - "```python\n", - "m.fs.flash.heat_duty.fix(0)\n", - "```\n", - "\n", - "For this module, we will use the following specifications:\n", - "* inlet overall molar flow = 1.0 (`flow_mol`)\n", - "* inlet temperature = 368 K (`temperature`)\n", - "* inlet pressure = 101325 Pa (`pressure`)\n", - "* inlet mole fraction (benzene) = 0.5 (`mole_frac_comp[0, \"benzene\"]`)\n", - "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", - "* The heat duty on the flash set to 0 (`heat_duty`)\n", - "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Write the code below to specify the inlet conditions and unit specifications described above\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add inlet specifications given above\n", - "m.fs.flash.inlet.flow_mol.fix(1)\n", - "m.fs.flash.inlet.temperature.fix(368)\n", - "m.fs.flash.inlet.pressure.fix(101325)\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", - "m.fs.flash.inlet.mole_frac_comp[0, \"toluene\"].fix(0.5)\n", - "\n", - "# Todo: Add 2 flash unit specifications given above\n", - "m.fs.flash.heat_duty.fix(0)\n", - "m.fs.flash.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Check the degrees of freedom again to ensure that the system is now square. You should see that the degrees of freedom is now 0.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Degrees of Freedom = 0\n" - ] - } - ], - "source": [ - "# Todo: print the degrees of freedom for your model\n", - "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initializing the Model\n", - "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - Optimal Solution Found.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_out: State Released.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume: Initialization Complete\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash.control_volume.properties_in: State Released.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2023-11-02 10:30:25 [INFO] idaes.init.fs.flash: Initialization Complete: optimal - Optimal Solution Found\n" - ] - } - ], - "source": [ - "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: \n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 135\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 72\n", - "\n", - "Total number of variables............................: 41\n", - " variables with only lower bounds: 3\n", - " variables with lower and upper bounds: 10\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 41\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.46e-11 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - "\n", - "Number of Iterations....: 0\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.6292494973376915e-12 1.4551915228366852e-11\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.6292494973376915e-12 1.4551915228366852e-11\n", - "\n", - "\n", - "Number of objective function evaluations = 1\n", - "Number of objective gradient evaluations = 1\n", - "Number of equality constraint evaluations = 1\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 1\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 0\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.000\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n", - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - ] - } - ], - "source": [ - "# Todo: create the ipopt solver\n", - "solver = SolverFactory(\"ipopt\")\n", - "\n", - "# Todo: solve the model\n", - "status = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Viewing the Results\n", - "\n", - "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", - "```python\n", - "print('Vap. Outlet Temperature = ', value(m.fs.flash.vap_outlet.temperature[0]))\n", - "```\n", - "\n", - "You can also find more information about a variable or an entire port using the `display` method from Pyomo:\n", - "```python\n", - "m.fs.flash.vap_outlet.temperature.display()\n", - "m.fs.flash.vap_outlet.display()\n", - "```\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cells below to show the current value of the flash vapor outlet pressure. This cell also shows use of the display function to see the values of the variables in the vap_outlet and the liq_outlet.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pressure = 101325.0\n", - "\n", - "Output from display:\n", - "vap_outlet : Size=1\n", - " Key : Name : Value\n", - " None : flow_mol : {0.0: 0.39611817487741735}\n", - " : mole_frac_comp : {(0.0, 'benzene'): 0.6339766485081294, (0.0, 'toluene'): 0.36602335149187054}\n", - " : pressure : {0.0: 101325.0}\n", - " : temperature : {0.0: 368.0}\n", - "liq_outlet : Size=1\n", - " Key : Name : Value\n", - " None : flow_mol : {0.0: 0.6038818251225827}\n", - " : mole_frac_comp : {(0.0, 'benzene'): 0.4121175977229309, (0.0, 'toluene'): 0.587882402277069}\n", - " : pressure : {0.0: 101325.0}\n", - " : temperature : {0.0: 368.0}\n" - ] - } - ], - "source": [ - "# Print the pressure of the flash vapor outlet\n", - "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", - "\n", - "print()\n", - "print(\"Output from display:\")\n", - "# Call display on vap_outlet and liq_outlet of the flash\n", - "m.fs.flash.vap_outlet.display()\n", - "m.fs.flash.liq_outlet.display()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.flash Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 0.0000 : watt : True : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol mole / second 1.0000 0.39612 0.60388 \n", - " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", - " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", - " temperature kelvin 368.00 368.00 368.00 \n", - " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", - "====================================================================================\n" - ] - } - ], - "source": [ - "m.fs.flash.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Studying Purity as a Function of Heat Duty\n", - "\n", - "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", - "\n", - "First, let's import the matplotlib package for plotting as we did in the previous module.\n", - "
\n", - "Inline Exercise:\n", - "Execute the cell below to import matplotlib appropriately.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exercise specifications:\n", - "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", - "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "scrolled": true, - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Simulating with Q = -17000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -16142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -15285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -14428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -13571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -12714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -10142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -9285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -8428.57142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -7571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -6714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -4142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -3285.7142857142862\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -2428.5714285714294\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -1571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -714.2857142857156\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 142.8571428571413\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 2714.2857142857138\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 3571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 4428.5714285714275\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 5285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 6142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 8714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 9571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 10428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 11285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 12142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 14714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 15571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 16428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 17285.714285714283\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 18142.857142857145\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 20714.28571428571\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 21571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 22428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 23285.714285714283\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 24142.857142857145\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 25000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Flash Unit Model Tutorial\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "## Key links to documentation\n", + "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" ] - }, - "metadata": { - "filenames": { - "image/png": "C:\\Users\\dkgun\\src\\dangunter\\examples\\idaes_examples\\notebooks\\_build\\jupyter_execute\\docs\\tut\\core\\flash_unit_doc_33_51.png" - } - }, - "output_type": "display_data" - } - ], - "source": [ - "# import the solve_successful checking function from workshop tools\n", - "from idaes_examples.mod.tut.workshoptools import solve_successful\n", - "\n", - "# Todo: import numpy\n", - "import numpy as np\n", - "\n", - "# create the empty lists to store the results that will be plotted\n", - "Q = []\n", - "V = []\n", - "\n", - "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", - "\n", - "# Todo: Write the for loop specification using numpy's linspace\n", - "for duty in np.linspace(-17000, 25000, 50):\n", - " # fix the heat duty\n", - " m.fs.flash.heat_duty.fix(duty)\n", - "\n", - " # append the value of the duty to the Q list\n", - " Q.append(duty)\n", - "\n", - " # print the current simulation\n", - " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", - "\n", - " # Solve the model\n", - " status = solver.solve(m)\n", - "\n", - " # append the value for vapor fraction if the solve was successful\n", - " if solve_successful(status):\n", - " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", - " print(\"... solve successful.\")\n", - " else:\n", - " V.append(0.0)\n", - " print(\"... solve failed.\")\n", - "\n", - "# Create and show the figure\n", - "plt.figure(\"Vapor Fraction\")\n", - "plt.plot(Q, V)\n", - "plt.grid()\n", - "plt.xlabel(\"Heat Duty [J]\")\n", - "plt.ylabel(\"Vapor Fraction [-]\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Repeat the exercise above, but create a figure showing the heat duty vs. the mole fraction of Benzene in the vapor outlet. Remove any unnecessary printing to create cleaner results.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Simulating with Q = -17000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -16142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -15285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -14428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -13571.428571428572\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -12714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -11000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -10142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -9285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -8428.57142857143\n" - ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -7571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -6714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5857.142857142857\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -5000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -4142.857142857143\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -3285.7142857142862\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -2428.5714285714294\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -1571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = -714.2857142857156\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 142.8571428571413\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 1857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 2714.2857142857138\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 3571.4285714285725\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 4428.5714285714275\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 5285.714285714286\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 6142.857142857141\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7000.0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 7857.142857142855\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 8714.285714285714\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 9571.428571428569\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 10428.571428571428\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 11285.714285714286\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", + "\n", + "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", + "\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to perform the imports. Let a workshop organizer know if you see any errors.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 12142.857142857141\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, + "cell_type": "code", + "source": [ + "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", + "from idaes.core import FlowsheetBlock\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to create the objects\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, + "cell_type": "code", + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: call pprint on the model\n", + "m.pprint()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 2.1 Define Properties\n", + "\n", + "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", + "\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "\n", + "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import and create the properties block.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 13857.142857142855\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", + " BTXParameterBlock,\n", + ")" + ], + "outputs": [], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.properties = BTXParameterBlock(\n", + " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", + ")" + ], + "outputs": [], + "execution_count": 7 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 2.2 Adding Flash Unit\n", + "\n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", + "\n", + "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", + "\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "\n", + "Some of the IDAES pre-written unit models:\n", + "* Mixer / Splitter\n", + "* Heater / Cooler\n", + "* Heat Exchangers (simple and 1D discretized)\n", + "* Flash\n", + "* Reactors (kinetic, equilibrium, gibbs, stoichiometric conversion)\n", + "* Pressure changing equipment (compressors, expanders, pumps)\n", + "* Feed and Product (source / sink) components\n", + "\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the Flash and create an instance of the unit model, attaching it to the flowsheet object.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 14714.285714285714\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, + "cell_type": "code", + "source": "from idaes.models.unit_models import Flash", + "outputs": [], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, + "cell_type": "code", + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 15571.428571428569\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 16428.571428571428\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 17285.714285714283\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 4 Set Operating Conditions\n", + "\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 18142.857142857145\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Todo: Call the python help on the degrees_of_freedom function\n", + "help(degrees_of_freedom)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: print the degrees of freedom for your model\n", + "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", + "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", + "\n", + "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", + "\n", + "As an example, to fix the molar flow of the inlet to be 1.0, you can use the following notation:\n", + "```python\n", + "m.fs.flash.inlet.flow_mol.fix(1.0)\n", + "```\n", + "\n", + "To specify variables that are indexed by components, you can use the following notation:\n", + "```python\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", + "```\n", + "\n", + "
\n", + "Note:\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "
\n", + "\n", + "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", + "\n", + "\n", + "To specify the value of a variable on the unit itself, use the following notation.\n", + "\n", + "```python\n", + "m.fs.flash.heat_duty.fix(0)\n", + "```\n", + "\n", + "For this module, we will use the following specifications:\n", + "* inlet overall molar flow = 1.0 (`flow_mol`)\n", + "* inlet temperature = 368 K (`temperature`)\n", + "* inlet pressure = 101325 Pa (`pressure`)\n", + "* inlet mole fraction (benzene) = 0.5 (`mole_frac_comp[0, \"benzene\"]`)\n", + "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", + "* The heat duty on the flash set to 0 (`heat_duty`)\n", + "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 19857.142857142855\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: Add inlet specifications given above\n", + "m.fs.flash.inlet.flow_mol.fix(1)\n", + "m.fs.flash.inlet.temperature.fix(368)\n", + "m.fs.flash.inlet.pressure.fix(101325)\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"benzene\"].fix(0.5)\n", + "m.fs.flash.inlet.mole_frac_comp[0, \"toluene\"].fix(0.5)\n", + "\n", + "# Todo: Add 2 flash unit specifications given above\n", + "m.fs.flash.heat_duty.fix(0)\n", + "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 20714.28571428571\n" - ] + "metadata": { + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, + "source": [ + "# Todo: print the degrees of freedom for your model\n", + "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 21571.428571428572\n" - ] + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 5 Initializing the Model\n", + "\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", + "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 22428.571428571428\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: initialize the flash unit\n", + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 6 Solving the Model\n", + "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 23285.714285714283\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: create the ipopt solver\n", + "solver = SolverFactory(\"ipopt\")\n", + "\n", + "# Todo: solve the model\n", + "status = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 7 Viewing the Results\n", + "\n", + "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", + "```python\n", + "print('Vap. Outlet Temperature = ', value(m.fs.flash.vap_outlet.temperature[0]))\n", + "```\n", + "\n", + "You can also find more information about a variable or an entire port using the `display` method from Pyomo:\n", + "```python\n", + "m.fs.flash.vap_outlet.temperature.display()\n", + "m.fs.flash.vap_outlet.display()\n", + "```\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cells below to show the current value of the flash vapor outlet pressure. This cell also shows use of the display function to see the values of the variables in the vap_outlet and the liq_outlet.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 24142.857142857145\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, + "cell_type": "code", + "source": [ + "# Print the pressure of the flash vapor outlet\n", + "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", + "\n", + "print()\n", + "print(\"Output from display:\")\n", + "# Call display on vap_outlet and liq_outlet of the flash\n", + "m.fs.flash.vap_outlet.display()\n", + "m.fs.flash.liq_outlet.display()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n", - "Simulating with Q = 25000.0\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, + "cell_type": "code", + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Exercise: Studying Purity as a Function of Heat Duty\n", + "\n", + "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", + "\n", + "First, let's import the matplotlib package for plotting as we did in the previous module.\n", + "
\n", + "Inline Exercise:\n", + "Execute the cell below to import matplotlib appropriately.\n", + "
" + ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "... solve successful.\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, + "cell_type": "code", + "source": "import matplotlib.pyplot as plt", + "outputs": [], + "execution_count": 42 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Exercise specifications:\n", + "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", + "* Specify the heat duty from -17000 to 25000 over 50 steps\n", + "\n" + ] }, { - "data": { - "image/png": "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", - "text/plain": [ - "
" + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# import the solve_successful checking function from workshop tools\n", + "from idaes_examples.mod.tut.workshoptools import solve_successful\n", + "\n", + "# Todo: import numpy\n", + "import numpy as np\n", + "\n", + "# create the empty lists to store the results that will be plotted\n", + "Q = []\n", + "V = []\n", + "\n", + "# re-initialize model\n", + "FlashInitializer.initialize(m.fs.flash)\n", + "\n", + "# Todo: Write the for loop specification using numpy's linspace\n", + "for duty in np.linspace(-17000, 25000, 50):\n", + " # fix the heat duty\n", + " m.fs.flash.heat_duty.fix(duty)\n", + "\n", + " # append the value of the duty to the Q list\n", + " Q.append(duty)\n", + "\n", + " # print the current simulation\n", + " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", + "\n", + " # Solve the model\n", + " status = solver.solve(m)\n", + "\n", + " # append the value for vapor fraction if the solve was successful\n", + " if solve_successful(status):\n", + " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", + " print(\"... solve successful.\")\n", + " else:\n", + " V.append(0.0)\n", + " print(\"... solve failed.\")\n", + "\n", + "# Create and show the figure\n", + "plt.figure(\"Vapor Fraction\")\n", + "plt.plot(Q, V)\n", + "plt.grid()\n", + "plt.xlabel(\"Heat Duty [J]\")\n", + "plt.ylabel(\"Vapor Fraction [-]\")\n", + "plt.show()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAATA1JREFUeJzt3QdYFNf+PvCXpYMUEQFFrKjYEARBNMYUW2K5KUZjRUSjSbwaNUUTozG5UWMSrzExlliwxh5NotfYjUYFxV6wK4oCYqMJLLv7f87xB39QVBaB2fJ+nmdkZ3Z2+bLDLq9nzpljodPpdCAiIiIyESqlCyAiIiIqTQw3REREZFIYboiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITIoVzIxWq8X169fh5OQECwsLpcshIiKiYhCX5UtLS0PVqlWhUj25bcbswo0INj4+PkqXQURERCVw9epVVKtW7Yn7mF24ES02eS+Os7Oz0uWYLbVajc2bN6N9+/awtrZWuhx6Ah4r48LjZTx4rPSTmpoqGyfy/o4/idmFm7xTUSLYMNwo+6Z2cHCQx4BvasPGY2VceLyMB49VyRSnSwk7FBMREZFJYbghIiIik8JwQ0RERCaF4YaIiIhMCsMNERERmRSGGyIiIjIpDDdERERkUhhuiIiIyKQw3BAREZFJYbghIiIik6JouPn777/RpUsXOcOnuJzyunXrnvqYnTt3olmzZrC1tYWvry+ioqLKpVYiIiIyDoqGm4yMDDRt2hQzZswo1v6XLl1Cp06d8OKLL+LIkSP44IMPMHDgQPz1119lXisREREZB0UnznzllVfkUlyzZs1CrVq18P3338v1Bg0aYM+ePfjvf/+LDh06lGGlRERE5etephpp2WoYIxsrFTyc7BT7/kY1K/i+ffvQtm3bQttEqBEtOI+TnZ0tl4JTpufNxioWUkbea89jYPh4rIwLj5fxH6vzyemYuesS/jx+A1odjFKgjwtWvhNaqs+pz++0UYWbxMREeHp6Ftom1kVguX//Puzt7R95zKRJkzBhwoRHtm/evFlONU/K2rJli9IlUDHxWBkXHi/jO1bXM4DNCSocuWUBHSzkNmsL40w3affuYuPGjaX6nJmZmaYZbkpizJgxGDlyZP66CEI+Pj5o3749nJ2dFa3NnIkELt7Q7dq1g7W1tdLl0BPwWBkXHi/jO1bejVtg9p54bDmdnH9fuwYeeP+F2mhUlX+nHj7zYnLhxsvLC0lJSYW2iXURUopqtRHEqCqxPEy86fnGVx6Pg/HgsTIuPF6G7+i1e5gTp8LJfQfluoUF8GqTKhj6oi8aVGGoeZg+v89GFW7CwsIeaeYSqVdsJyIiMgbxtzLx+foT2HX2phy0rLIAujStKkNNXU8npcszCYqGm/T0dJw/f77QUG8xxNvNzQ3Vq1eXp5QSEhKwaNEief+QIUPw008/4eOPP8aAAQOwfft2rFy5Ehs2bFDwpyAiIiqeU9dT0W9+DFLSs2GpskBQJQ3+06s16lVxVbo0k6LodW4OHjyIwMBAuQiib4y4PW7cOLl+48YNxMfH5+8vhoGLICNaa8T1ccSQ8Llz53IYOBERGbwDl2+jx5x9MtiI005/DW+F3r5a1HJ3VLo0k6Noy80LL7wAne7xPcGLuvqweMzhw4fLuDIiIqLSsz0uCe8uOYTsXC2a16yIueHN4WAFnFS6MBNlVH1uiIiIjM26wwkYteooNFodXvLzwIxezWBvY8lrEZUhhhsiIqIyEvXPJXzxxyl5+/VAb0zp5g9rS85ZXdYYboiIiEqZ6HIxbes5/LDtnFzv37ImxnVuCJUYGkVljuGGiIioFGm1Okz44yQW7rsi10e2q4d/v+QLC3EhGyoXDDdERESlRK3RYtTKo/j96HV5Ub4JXRuhX1hNpcsyOww3REREpeB+jgbvLY3FjjM3YaWywPfdm+JfAd5Kl2WWGG6IiIie0b37akRGHcDBK3dgZ63CzN5BeNHPQ+myzBbDDRER0TNITs2SVx2OS0yDs50V5vdvjuCabkqXZdYYboiIiJ5hnqg+86IRfzsT7hVssTgyhJNeGgCGGyIiohKIS0xFv3kxSE7Lho+bPZZEhqJGJU6lYAgYboiIiPQUe+UOIhbEIDUrF/U9nbAoMgSeznZKl0X/h+GGiIhID7vO3sSQxbG4r9agWXVXLOgfAhcHa6XLogIYboiIiIrpj6PXMXLlEag1OrSpVxkz+zSDgw3/lBoaHhEiIqJiWLL/Cj5ffwI6HdClaVV8/1ZT2FhxnihDxHBDRET0lHmiftp+Ht9vOSvX+7SojgldG8OS80QZLIYbIiKiJ8wT9Z8NpzH/n0tyXcwRJeaK4jxRho3hhoiIqAi5Gi0+XnMMaw8lyPXPOzdE5HO1lC6LioHhhoiI6CFZag2GLjuMraeT5OmnKW/6482gakqXRcXEcENERFRAapYagxYeRPSl27LD8IxezdCuoafSZZEeGG6IiIj+T0p6NsLnx+Dk9VRUsLXC3PBgtKhdSemySE8MN0RERACu3clE33kxuJSSgUqONlg4IASNvV2ULotKgOGGiIjM3rmkNBlsElOz4O1qLyfArF25gtJlUQkx3BARkVk7evUu+i+IwZ1MNepUdsSSgaGo4mKvdFn0DBhuiIjIbP1zPgWDFh1EZo4G/tVcEBURAjdHG6XLomfEcENERGZp04kbGPbrEeRotGjlWwmz+wbLTsRk/HgUiYjI7Kw4EI8xa49DqwM6NvLCDz0DYGtlqXRZVEoYboiIyKzM3nUBk/4XJ2/3CPbBxDeacJ4oE8NwQ0REZjMB5jebzmDWrgtyfXCb2hjd0Y/zRJkghhsiIjJ5Gq0OY9cdx68xV+X66Ff8MKRNHaXLojLCcENERCYtO1eDESuOYOPxRIizTxNfb4K3Q6orXRaVIYYbIiIyWRnZuRiyJBa7z6XAxlKFH94OwCtNqihdFpUxhhsiIjJJdzJyEBF1AEeu3oWDjSXm9A3Gc3XdlS6LygHDDRERmZzEe1noOy8a55LT4epgLS/OF+DjqnRZVE4YboiIyKSIiS/7zI1Gwt378HK2k/NE1fV0UrosKkcMN0REZDJOXr+H8PkxSEnPQS13RxlsqlV0ULosKmcMN0REZBJiLt1GZNQBpGXnomEVZywcEILKTrZKl0UKYLghIiKjtz0uCe8uOYTsXC1Carphbv9gONtZK10WKYThhoiIjNq6wwn4cNVR5Gp1eNnPAzN6N4OdNeeJMmcMN0REZLQW7r2M8b+flLdfD/TGlG7+sLZUKV0WKYzhhoiIjHKeqB+2ncO0refkev+WNTGuc0OoOAEmMdwQEZGx0Wp1+PLPU4jae1muj2hbD8Ne9uUEmJSP4YaIiIyGWqPFx6uP4bfDCXJ9QtdGCG9ZU+myyMAw3BARkVHIUmvw/tJD2BaXDCuVBb7v3hT/CvBWuiwyQAw3RERk8FKz1BgYdRAxl2/D1kqFmX2a4SU/T6XLIgPFcENERAbtZlq2vOrwqRupcLKzwvz+zdG8ppvSZZEBY7ghIiKDdfV2JvrNj5HzRblXsMXCAc3RqKqL0mWRgWO4ISIig3QuKQ1958UgMTUL1SraY0lkKGq6OypdFhkBhhsiIjI4R67eRf8FMbibqUZdjwpYHBkKLxc7pcsiI8FwQ0REBuWf8ykYtOggMnM0CPBxxYL+zVHR0UbpssiIMNwQEZHB2HTiBob9egQ5Gi2e83XH7L5BcLTlnyrSD39jiIjIIKw8cBWj1x6DVge80tgL094OgK0VJ8Ak/THcEBGR4ub8fQETN8bJ2z2CfTDxjSaw5DxRVEIMN0REpOgEmFP+OoOZOy/I9cFtamN0Rz/OE0XPhOGGiIgUodHqMHbdCfwaEy/XP+noh3dfqKN0WWQCGG6IiKjcZedqMHLFUWw4fgOikWbi603QM6S60mWRiWC4ISKicpWRnYshS2Kx+1wKrC0tMK1HIDr5V1G6LDIhDDdERFRu7mbmICLqAA7H34W9taUc6v18vcpKl0UmRqV0ATNmzEDNmjVhZ2eH0NBQxMTEPHH/adOmoX79+rC3t4ePjw9GjBiBrKyscquXiIhKJik1Cz1m75fBxsXeGksGhjLYkOmFmxUrVmDkyJEYP348Dh06hKZNm6JDhw5ITk4ucv9ly5Zh9OjRcv/Tp09j3rx58jk+/fTTcq+diIiK78qtDHSbtRdnktLg4WSLlYPDEFSjotJlkYlS9LTU1KlTMWjQIERERMj1WbNmYcOGDZg/f74MMQ/bu3cvWrVqhV69esl10eLTs2dPREdHP/Z7ZGdnyyVPamqq/KpWq+VCysh77XkMDB+PlXExxOMVl5iGAQtjcTM9B9Xd7LEgPAjV3ewMqkYlGOKxMmT6vE6KhZucnBzExsZizJgx+dtUKhXatm2Lffv2FfmYli1bYsmSJfLUVUhICC5evIiNGzeib9++j/0+kyZNwoQJEx7ZvnnzZjg4OJTST0MltWXLFqVLoGLisTIuhnK8LqUBs09b4r7GAlUddBhUKw0n9u/ECaULMyCGcqwMXWZmpuGHm5SUFGg0Gnh6ehbaLtbj4h5cpfJhosVGPO65556TF37Kzc3FkCFDnnhaSoQnceqrYMuN6KvTvn17ODs7l+JPRPomcPGGbteuHaytrZUuh56Ax8q4GNLx+vtcCmb9egRZGi2aVXfFnD6Bsq8NGd6xMgZ5Z15MbrTUzp07MXHiRPz888+y8/H58+cxfPhwfPXVV/j888+LfIytra1cHiZ+kfjLpDweB+PBY2VclD5efxy9jpErj0Ct0aFNvcqY2acZHGyM6k+O2RwrY6HPa6TYb5q7uzssLS2RlJRUaLtY9/LyKvIxIsCIU1ADBw6U602aNEFGRgbeeecdfPbZZ/K0FhERKWtp9BV55WGdDujsXwVTuwfAxoqfz1R+FPtts7GxQVBQELZt25a/TavVyvWwsLDHnm97OMCIgCSI01RERKQc8Tk8Y8d5fPbbg2DTO7Q6fng7kMGGyp2ibYSiL0x4eDiCg4NlB2FxDRvREpM3eqpfv37w9vaWnYKFLl26yBFWgYGB+aelRGuO2J4XcoiISJlgM3Hjafyy+5JcH/qiL0a1r8cJMMn8wk2PHj1w8+ZNjBs3DomJiQgICMCmTZvyOxnHx8cXaqkZO3asfKOIrwkJCahcubIMNl9//bWCPwURkXnL1Wjx6W/HsfLgNbk+tlMDDGxdW+myyIwp3rtr6NChcnlcB+KCrKys5AX8xEJERMrLUmswfPlh/HUyCSoLYPKb/uge7KN0WWTmFA83RERknNKzczF48UH8c/4WbCxVmN4zEB0bFz0ghKg8MdwQEZHe7mTkoH/UARy9eheONpaY0y8YrXzdlS6LSGK4ISIivSTey0LfedE4l5yOig7WiIoIQVMfV6XLIsrHcENERMV2KSUDfeZGI+HufXg522FxZAjqejopXRZRIQw3RERULKeup6Lf/BikpGejlrujDDbVKnKOPjI8DDdERPRUBy/fRkTUAaRl5aJhFWcsHBCCyk6PTm1DZAgYboiI6Il2nEnGu0tikaXWonnNipjXvzmc7TgXEhkuhhsiInqs38UEmCuOIFerw4v1K+Pn3kGwt+EV4cmwMdwQEVGRluy/gs/XP5gn6l8BVfHdW01hbcl5osjwMdwQEdEj80T9vPMCvv3rjFzvF1YDX3RpBJW4BDGREWC4ISKix06AOewlX4xoxwkwybgw3BARUZETYH7euSEin6uldFlEemO4ISKiQhNgWqos8M2b/ugWVE3psohKhOGGiMjMZWTn4p0CE2D+2CsQHRpxAkwyXgw3RERm7OEJMH/pF4yWnACTjBzDDRGRmeIEmGSqGG6IiMzQZTEB5rxoXLvzYALMJQND4OvBCTDJNDDcEBGZGU6ASaaO4YaIyIxwAkwyBww3RERmYueZZAwpMAHm3PDmcLHnBJhkehhuiIjMwB9Hr2PE/02A+UL9ypjJCTDJhDHcEBGZuKXRVzB23YMJMLs2fTABpo0VJ8Ak08VwQ0RkwvNEzdx1AVM2PZgAs0+L6viya2NOgEkmj+GGiMhEg82k/8Vhzt8X5frQF30xqj0nwCTzwHBDRGRitDrgs/WnsCo2Qa6P7dQAA1vXVrosonLDcENEZEKyc7WIOqvC0dsJEGefJr/pj+7BPkqXRVSuGG6IiExoAszBSw7j6G0VrC0t8GPPZujYmBNgkvlhuCEiMgF3M3PQf8EBHLl6FzYqHX7pG4Q2fgw2ZJ4YboiIjFxSahb6zYvBmaQ0uNhbYUCdLLSsU0npsogUwwsdEBEZsSu3MtBt1l4ZbDydbfFrZAhqcv5LMnNsuSEiMlJxianoOy8GN9OyUaOSA5ZEhsLLyRrnlC6MSGEMN0RERij2yh0MiDqAe/fV8PNywqIBIfBwtoNarVa6NCLFMdwQERmZv8/exODFsbiv1qBZdVcs6B8CFwdOgEmUh+GGiMiIbDx+A8OXH4Zao0Pruu6Y3TcIDjb8KCcqiO8IIiIjseJAPMasPS6vQNypSRVM7dEUtlac2ZuoROHm2LFj0FfDhg1hZcXsRERUGub8fQETN8bJ228398HXrzeBJSfAJCpSsdJHQECAnGxNTMRWHCqVCmfPnkXt2pzLhIjoWYjP3W//OoOfd16Q64Ofr43Rr/hxAkyiJyh200p0dDQqV65crDdi48aNi/u0RET0GBqtDuPWn8DS6Hi5/klHP7z7Qh2lyyIyjXDTpk0b+Pr6wtXVtVhP+vzzz8Pe3v5ZayMiMls5uVqMXHkEfx67AdFI8/VrTdArtLrSZRGZTrjZsWOHXk+6cePGktZDRGT27udo8O7SWOw8c1NOgDm1ewC6NK2qdFlE5jH9wj///IPs7OzSq4aIyMyJi/L1nRctg42dtQq/9AtmsCEqz3DzyiuvICEh4VmegoiI/o+YRqHnnP04eOUOnOyssDgyFC/U91C6LCKj80xjtYs7eoqIiJ7s2p1MOU/UpZQMuFewwcIBIWhU1UXpsoiMEi9EQ0SksPPJ6fJU1I17WfB2tcfiyBDUrlxB6bKIzDPczJ49G56enqVXDRGRmTl+7R7CF8TgdkYO6lR2xJKBoajiwtGmRIqFm169ej3TNyciMmf7LtzCoEUHkZ6diybeLvJUlJujjdJlEZlHh+I33ngDqampxX7S3r17Izk5+VnqIiIyaVtPJckWGxFsQmu5YdmgUAYbovJsuVm/fj1u3rxZ7E7Gf/zxB7766it4eLCXPxHRw347fA0frjomr0DctoEHfurVDHbWnACTqFzDjQgs9erVK7VvSkRkrhbuvYzxv5+Ut18P9MaUbv6wtnymq3IQUXlcoVjw9vbW+zFERKZK/Cfxx+3nMXXLWbkeHlYD47s0goozexMpN7cUERGVjFarw9cbT2PenktyffjLdfFB27qc2ZuojPA6N0REZShXo8XotcexOvaaXB/XuSEGPFdL6bKITBrDDRFRGcnO1WD4r0ew6WQixNmnb970x1vBPkqXRWTyGG6IiMpARnYu3ll8EP+cvwUbSxV+7BWIDo28lC6LyCww3BARlbK7mTnov+AAjly9CwcbSzmzdytfd6XLIjIbDDdERKUoOTVLToB5JikNrg7WiIoIQYCPq9JlEZkVvS+ukJSUhL59+6Jq1aqwsrKCpaVloUVfM2bMQM2aNWFnZ4fQ0FDExMQ8cf+7d+/i/fffR5UqVWBrayuvv7Nx40a9vy8RUWmLv5WJbrP2yWDj4WSLFe+EMdgQGUPLTf/+/REfH4/PP/9cBoxnGcq4YsUKjBw5ErNmzZLBZtq0aejQoQPOnDlT5NWNc3Jy0K5dO3nf6tWr5bV0rly5AldXfngQkbLOJKbJmb2T07JR3c0BSweGwsfNQemyiMyS3uFmz5492L17NwICAp75m0+dOhWDBg1CRESEXBchZ8OGDZg/fz5Gjx79yP5i++3bt7F3715YW1vLbaLV50mys7Plkidvjiy1Wi0XUkbea89jYPh4rJ5O9K0ZuPgQ7t3PRT2PCljQPwgeTtaKvGY8XsaDx0o/+rxOFjpx2Uw9NGzYEEuXLkVgYCCehWiFcXBwkC0wr732Wv728PBweepJzGf1sFdffRVubm7yceL+ypUry5nJP/nkk8eeEvviiy8wYcKER7YvW7ZMPg8R0bM4c88Cc+NUyNFaoGYFHd7x08Dxwf+9iKgUZWZmyr/59+7dg7Ozc+m23IhTR6JVZfbs2U9tNXmSlJQUaDQaeHp6Ftou1uPi4op8zMWLF7F9+3Y567joZ3P+/Hm89957Ms2NHz++yMeMGTNGnvoq2HLj4+OD9u3bP/XFobIjjtmWLVvkaca8VjgyTDxWj7flVDJ+WXkUaq0OLeu44eeeAXC0VXacBo+X8eCx0k/emZfi0Ptd2KNHD5me6tSpI1s+Hj4g4rRRWdFqtbK/zZw5c2RLTVBQEBISEvDtt98+NtyITsdieZiom79MyuNxMB48VoWJKw5/vPootDqgYyMv/NAzALZWhjOzN4+X8eCxKh59XqMStdyUBnd3dxlQxOirgsS6l1fRF7oSHZjFD1fwFFSDBg2QmJgoT3PZ2NiUSm1ERE+y4J9LmPDHKXn7raBqmPRGE1hxZm8ig6F3uBF9YkqDCCKi5WXbtm35fW5Ey4xYHzp0aJGPadWqlewrI/ZTqR58kJw9e1aGHgYbIiprooviD9vOYdrWc3I98rla+OzVBpzZm8jAlOjksOgrs27dOpw+fVquN2rUCF27dtX7OjeiL4wIS8HBwQgJCZGtQhkZGfmjp/r16yeHe0+aNEmuv/vuu/jpp58wfPhw/Pvf/8a5c+cwceJEDBs2rCQ/BhGRXjN7f/nnKUTtvSzXR7Wrh6Ev+XJmbyJTCDeiE68YtST6utSvX19uE+FDdNIVw7hFXxx9+u/cvHkT48aNk6eWxPDyTZs25XcyFtfTyWuhEcT3+OuvvzBixAj4+/vL4COCjhgtRURUljN7f7LmONYcejCz94SujRDesuQDKojIwMKNaCURAWb//v1yWLZw69Yt9OnTR94nAo4+xCmox52G2rlz5yPbwsLC5PcmIioPWWoNhv16GJtPJcFSZYFvu/njjWbVlC6LiEoz3OzatatQsBEqVaqEyZMnyz4xRESmIj07F4PzZva2UmFGr2Zo17Dw5SuIyATCjRhWnZaW9sj29PR0duolIpOa2Tt8wQEcvXoXjmJm7/BgtKzDmb2JjIHeYxc7d+6Md955B9HR0XLkgFhES86QIUNkp2IiImOXlJqF7rP3yWAjZvZeNqgFgw2RKYeb6dOnyz43ou+LmMlbLOJ0lK+vL3744YeyqZKIqBxn9n5r1j6cTUqHp7MtVg4OQ1PO7E1k2qelxAzcYl4nMQw7b5oEcSE9EW6IiIwZZ/YmMg0lngSlbt26ciEiMgWH4++g/4IDuHdfDT8vJywaEAIPZzulyyKisgo34mJ7X331FRwdHQtNQlmUqVOnlqQOIiLF7D2fgoGLDiIzR4PA6q5Y0L85XB04QILIpMPN4cOH5eylebeJiEzFXycT8e9lh5Gj0eI5X3fM7huk+MzeRPRsivUO3rFjR5G3iYiM2Roxs/eaY9BodejQyBPTewYa1MzeRFROo6UGDBhQ5HVuxJxQ4j4iImMQ9c8ljFp1VAabbkHV5AX6GGyIzDTcLFy4EPfv339ku9i2aNGi0qqLiKjsZvbeeg5f/HFKrg9oVQtT3vSHlaXeH4dEZKCKfWI5NTU1/6J9ouVGXN+m4CzhGzduhIeHR1nVSURUKjN7/2fDacz/55JcH9G2Hoa9zJm9icw23Ijr24gPALHUq1fvkfvF9gkTJpR2fUREpTaz9+i1x7E69sHM3uO7NEREq1pKl0VESoYb0ZFYtNq89NJLWLNmTaGJM8WcUjVq1EDVqlXLokYiomeSnavB8F+PYNPJRKgsgG+7NcWbQZzZmwjmHm7atGkjv166dAnVq1dnMy4RGYWM7FwMWRKL3edSYGOpkiOiOjb2UrosIipDeveg2759O1avXv3I9lWrVsnOxkREhuJeplpOpyCCjYONJeb3b85gQ2QG9A43kyZNgrv7o7Pjis7EEydOLK26iIieSXJaFnrM2YdD8XfhYm+NJQND8VxdzuxNZA70vgxnfHw8atV6tBOe6HMj7iMiUtrV25myxebyrUxUdrLF4sgQ+Hk5K10WERlqy41ooTl27Ngj248ePYpKlSqVVl1ERCVyPjkNb83aJ4ONj5s9Vg8JY7AhMjN6t9z07NkTw4YNg5OTE55//nm5bdeuXRg+fDjefvvtsqiRiKhYjl+7h/AFMbidkYO6HhWwODIUXi6c2ZvI3OgdbsTs4JcvX8bLL78MK6sHD9dqtejXrx/73BCRYqIv3kLkwoNIz86FfzUXREWEwM2RM3sTmSO9w424ps2KFStkyBGnouzt7dGkSRPZ54aISAnb45Lw7pJDyM7VokVtN/zSLxhOdtZKl0VExhJu8oirFBd1pWIiovL0+9HrGLniCHK1OrRt4IGfejWDnTUnwCQyZyUKN9euXcPvv/8uR0fl5OQUum/q1KmlVRsR0RMtjb6CsetOQKcDXguoim/fagprToBJZPb0Djfbtm1D165dUbt2bcTFxaFx48ayD46YmqFZs2ZlUyUR0UNm7bqAyf+Lk7f7tqiBCV0bQSXmViAis6f3f3HGjBmDDz/8EMePH5czg4t5pq5evSqnZ3jrrbfKpkoiov8j/iP1zaa4/GDz/ot18OW/GGyI6BnCzenTp+XIKEGMlrp//z4qVKiAL7/8Et98842+T0dEVGxarU6ehpq584JcH/OKHz7q4Me57ojo2cKNo6Njfj+bKlWq4MKFBx8yQkpKir5PR0RULGqNFiNWHsHS6HiILDPpjSYY3KaO0mURkSn0uWnRogX27NmDBg0a4NVXX8WoUaPkKaq1a9fK+4iISluWWoP3lx7CtrhkWKks8N8eAejStKrSZRGRqYQbMRoqPT1d3p4wYYK8La57U7duXY6UIqJSl5alxsCFBxF96TZsrVSY1ScIL/p5KF0WEZlKuNFoNHIYuL+/f/4pqlmzZpVVbURk5sQ0Cv0XxODYtXuoYGuFeeHBCK3NOeyIqBT73FhaWqJ9+/a4c+eOPg8jItJb4r0sdJ+9TwYbMY3Cr4NaMNgQUdl0KBbXtbl48aK+DyMiKrYrtzLQbdZenE9Oh5ezHVYODkOTai5Kl0VEphpu/vOf/8jr3Pz555+4ceMGUlNTCy1ERM/iTGIaus3ah2t37qNmJQesGhIGX48KSpdFRKbcoViMkBLEVYoLXltCXFhLrIt+OUREJXE4/g76LziAe/fV8PNywqLIEHg42SldFhGZerjZsWNH2VRCRGZt7/kUDFx0EJk5GgRWd0VU/xC4OHBmbyIqw3Ajrko8Y8YMOc2CcPToUTRs2BDW1vzwIaJns/lkIob+ehg5uVq08q2EOX2D4Whbonl9iYiK3+dm6dKlcqqFPK1bt5ZzShERPYvfDl/Du0sPyWDTvqEn5oU3Z7AhomdS7E8Q0afmSetERPpavO8yPl9/Ut5+o5k3przpDytLvcc5EBEVwv8eEVG5E/85+nnnBXz71xm53r9lTYzr3JAzexNR+YebU6dOITExMf/DKS4uLn8qhjx5Vy8mIiqK+OyY/L84zP77wfWyhr3kixHt6nFmbyJSJty8/PLLhU5Hde7cWX4VH0ocCk5ET6PR6jB23Qn8GhMv18d2aoCBrWsrXRYRmWu4uXTpUtlWQkQmTa3RYsSKI/jz2A2Is0+T3miCHs2rK10WEZlzuKlRo0bZVkJEJitLrcF7Sw9he1wyrC0tMK1HIDr5V1G6LCIyUexQTERlKi1LjciFBxFz6TbsrFWY1ScIL9T3ULosIjJhDDdEVGZuZ+QgfH4Mjifcg5OtFeb1b46QWm5Kl0VEJo7hhojKROK9LPSZFy1n9nZztMGiASFo7M2ZvYmo7Ol1tSwxIio+Ph5ZWVllVxERGb0rtzLQbdZeGWy8nO2wcnAYgw0RGW648fX15bQLRPRYZxLT0G3WPly7cx81Kzlg1ZAw+HpUULosIjIjeoUblUqFunXr4tatW2VXEREZrSNX76L77H24mZYNPy8nrBwSBh83B6XLIiIzo/ckLpMnT8ZHH32EEydOlE1FRGSU9l5IQe9f9uPefTUCq7ti+Tst4OFkp3RZRGSG9O5Q3K9fP2RmZqJp06awsbGBvb19oftv375dmvURkRHYeioJ7y17MLN3K99KmNM3mDN7E5Fi9P70mTZtWtlUQkRGaf2RBIxceVROrdCuoSd+7BkIO2tLpcsiIjOmd7gJDw8vm0qIyOgs2X8Fn68/ATHl3OuB3pjSzR/Wlnqf7SYiKlUlajcWk2OuW7cOp0+fluuNGjVC165dYWnJ/60RmYuZOy/gm01x8nbfFjUwoWsjqMSkUURExhZuzp8/j1dffRUJCQmoX7++3DZp0iT4+Phgw4YNqFOnTlnUSUQGQlwS4tu/zuDnnRfk+nsv1MFHHerDwoLBhogMg97tx8OGDZMBRlzr5tChQ3IRF/arVauWvK8kZsyYgZo1a8LOzg6hoaGIiYkp1uOWL18uP1Bfe+21En1fItKPVqvDuPUn84PNJx398HFHPwYbIjLucLNr1y5MmTIFbm7/f36YSpUqySHi4j59rVixAiNHjsT48eNlUBKjsDp06IDk5OQnPu7y5cv48MMP0bp1a72/JxHpL1ejxahVR7F4/xWILPOf1xrj3RfYUktEJhBubG1tkZaW9sj29PR0OTRcX1OnTsWgQYMQERGBhg0bYtasWXBwcMD8+fOf2Oend+/emDBhAmrXrq339yQi/ai1wLAVx/Db4QRYqiwwrUcA+rSooXRZRESl0+emc+fOeOeddzBv3jyEhITIbdHR0RgyZIjsVKyPnJwcxMbGYsyYMYWugty2bVvs27fvsY/78ssv4eHhgcjISOzevfuJ3yM7O1sueVJTU+VXtVotF1JG3mvPY2D47mbcx5w4Fc7eS4aNlQrTe/jjZT8PHjsDxfeW8eCx0o8+r5Pe4Wb69OlyOHhYWBisra3lttzcXBlsfvjhB72eKyUlRbbCeHp6Ftou1uPiHozCeNiePXtksDpy5Eixvofo7CxaeB62efNm2UJEytqyZYvSJdATZOYCs09b4nK6CjYqHQbVUyP74kFsvKh0ZfQ0fG8ZDx6r4hEXEC6zcOPq6or169fj3Llzcii46EjYoEEDOaFmWROnw/r27YtffvkF7u7uxXqMaBUSfXoKttyIkV3t27eHs7NzGVZLT0vg4g3drl27/JBMhiUlPRsRUbG4nJ4OB0sd5oUHIbhW8d53pBy+t4wHj5V+8s68FEeJr48uJtDMCzQlHSkhAoq4Nk5SUlKh7WLdy8vrkf0vXLggOxJ36dIlf5tWq5VfrayscObMmUeGoos+QmJ5mPhF4i+T8ngcDNO1O5noO+8gLqVkoHIFGwyokymDDY+V8eB7y3jwWBWPPq9RiS4lKk4LNW7cWA7dFou4PXfuXL2fR3RADgoKwrZt2wqFFbEuTns9zM/PD8ePH5enpPIWcTrsxRdflLdFiwwRPZsLN9PRfdY+GWy8Xe3x68AQVOUZXCIyInq33IwbN06OcPr3v/+dH0BE598RI0bI692Izr76EKeMRB+e4OBg2UFZzF2VkZEhR0/lTdTp7e0t+87kBamHT5MJD28nIv2dvH4P/ebF4FZGDupUdsSSgaFwd7DCSaULIyIqy3Azc+ZM2eelZ8+e+dtE64m/v78MPPqGmx49euDmzZsyNCUmJiIgIACbNm3K72QsApMYQUVEZSv2ym30X3AAaVm5aFTVGYsGhKBSBVuO5CAi0w834oNOtLI8TJxeEqOmSmLo0KFyKcrOnTuf+NioqKgSfU8i+v92n7uJdxbF4r5ag+Y1K2Je/+ZwtmMfACIyTno3iYjRSqL15mFz5syRF9YjIuOy6UQiIqMOymDzfL3KWDQglMGGiIyaVUk7FIvrxLRo0SL/In7i9JHoH1Nw2LXom0NEhmtN7DV8vOYYNFodXmnshR/eDpQX6iMiMqtwc+LECTRr1ix/aHbekG6xiPvycCI9IsO2aN9lOQmm8FZQNUx6owmsLBlsiMgMw82OHTvKphIiKhc6nU7O6v3tX2fkekSrmvi8U0OoVPwPCRGZhhJfxI+IjDPYTN4Uh9m7HsyfMOzluhjRti5bWonIpJQo3Bw8eBArV66U/WzE5JcFrV27trRqI6JSJPrVfL7+BJZFx8v1sZ0aYGDr2kqXRURU6vQ+wb58+XK0bNlSziv122+/yaHhJ0+exPbt2+Hi4lL6FRLRM1NrtBi58ogMNqKRZvIbTRhsiMhk6R1uJk6ciP/+97/4448/5PQJYiZwMYN39+7dUb169bKpkohKLEutwbtLYrH+yHVYqSww/e1AvB3C9yoRmS69w40YIdWpUyd5W4QbMVWCOF8vpl8Q17ohIsORkZ2LAVEHsPV0MmytVJjTLwhdmlZVuiwiIsMKNxUrVkRaWpq8LeZ8yhv+fffuXWRmZpZ+hURUInczc9B7bjT2XrgFRxtLLBwQgpf8HkxrQkRkyvTuUPz8889jy5YtaNKkCd566y0MHz5c9rcR215++eWyqZKI9JKcliUnwIxLTIOrgzUWRoSgqc+DSWaJiExdscONaKERM2//9NNPyMrKkts+++wzWFtbY+/evXjzzTcxduzYsqyViIoh4e599JkbjUspGfBwssXiyFDU93JSuiwiIsMLN2LW7+bNm2PgwIF4++235TYxW/fo0aPLsj4i0sPFm+ky2Fy/l4VqFe2xdGAoalRyVLosIiLD7HOza9cuNGrUCKNGjUKVKlUQHh6O3bt3l211RFRsp66novvsfTLY1KnsiFVDwhhsiMgsFTvctG7dGvPnz8eNGzfw448/4vLly2jTpg3q1auHb775BomJiWVbKRE9VuyVO3h7zj6kpOegUVVnrBwchiou9kqXRURkHKOlHB0dERERIVtyzp49KzsVz5gxQ17jpmvXrmVTJRE91j/nU9B3XjRSs3IRXKMilg1qgUoVbJUui4hIMc80BbCvry8+/fRT2ZHYyckJGzZsKL3KiOipNp9MRMSCA8jM0aB1XXcsigyBi7210mURERnnxJl///23PE21Zs0a2bFYXKE4MjKydKsjosdadzgBo1YdlXNGdWjkiek9A2FrZal0WURExhVurl+/jqioKLmcP39ezjE1ffp0GWzE6SoiKh9L9l+Rk2DqdMAbzbwx5U1/WFk+U0MsEZH5hZtXXnkFW7duhbu7O/r164cBAwagfv36ZVsdET1i1q4LmPy/OHm7X1gNfNGlEVQqC6XLIiIyvnAjLta3evVqdO7cGZaWbPomKm86nQ7fbz6Ln3acl+vvv1gHH7avL+d2IyKiEoSb33//vbi7ElEp02p1+PLPU4jae1muf9LRD+++UEfpsoiITKtDMRGVj1yNFp+sOY41h65BNNJ8+a/G6NuihtJlEREZLIYbIgOWnavBB8uP4H8nEmGpssB3b/nj9cBqSpdFRGTQGG6IDNT9HA0GL4nF32dvwsZShR97BaJDIy+lyyIiMngMN0QGKDVLjcioAzhw+Q7srS0xp18QWtetrHRZRERGgeGGyMDczshB+PwYHE+4Byc7K0RFNEdQDTelyyIiMhoMN0QGJCk1C33mRuNccjrcHG2waEAIGnu7KF0WEZFRYbghMhBXb2ei99xoxN/OhJezHZYMDIWvRwWlyyIiMjoMN0QG4Hxymgw2SanZqO7mgKUDQ+Hj5qB0WURERonhhkhhJxLuod/8GNnXpp5nBSyODIWns53SZRERGS2GGyIFHbx8GxELDiAtOxf+1VywMCIEFR1tlC6LiMioMdwQKURcv2bw4ljcV2sQUssN88KD4WRnrXRZRERGj+GGSAGbTiRi2K+HkaPRok29ypjVJwj2NpyQloioNDDcEJWztYeu4aPVx6DR6vBqEy9M6xEIGyuV0mUREZkMhhuicrR432V8vv6kvN0tqBomv9EEVpYMNkREpYnhhqiczNx5Ad9sipO3+7esiXGdG0KlslC6LCIik8NwQ1TGdDodvtt8BjN2XJDr/37JFyPb1YOFBYMNEVFZYLghKkNarQ4T/jiJhfuuyPXRr/hhSJs6SpdFRGTSGG6IykiuRovRa49jdew1iEaaL//VGH1b1FC6LCIik8dwQ1QGcnK1+GDFYWw8nghLlQW+e8sfrwdWU7osIiKzwHBDVMru52gwZEksdp29CRtLFab3DETHxl5Kl0VEZDYYbohKUVqWGpELDyLm0m3YWaswp28wnq9XWemyiIjMCsMNUSm5k5GD8AUxOHbtHpxsrTA/ojma13RTuiwiIrPDcENUCpJTs9BnXjTOJqXDzdEGiwaEoLG3i9JlERGZJYYbomd07U4m+syNxuVbmfB0tsWSyFDU9XRSuiwiIrPFcEP0DC7eTEfvudG4cS8L1SraY9nAFqheyUHpsoiIzBrDDVEJnb6Rir7zopGSnoM6lR2xdGALeLnYKV0WEZHZY7ghKoHD8XcQPj8GqVm5aFjFGYsjQ1Cpgq3SZREREcMNkf72XkjBwIUHkZmjQbPqrlgQEQIXe2ulyyIiov/DcEOkh+1xSXh3ySFk52rRyreSvI6Noy3fRkREhoSfykTF9Oex6/hg+RHkanVo28ATP/UKhJ21pdJlERHRQxhuiIph5cGrGL3mGLQ6oGvTqvi+e1NYW6qULouIiIrAcEP0FAv+uYQJf5ySt3uG+OA/rzWRk2ESEZFhYrghegydTocZO87ju81n5fqg1rXw6asNYGHBYENEZMgYbogeE2y+2XQGs3ZdkOsftK2L4S/XZbAhIjICBtFpYMaMGahZsybs7OwQGhqKmJiYx+77yy+/oHXr1qhYsaJc2rZt+8T9ifSl1eowbv3J/GAztlMDfNC2HoMNEZGRUDzcrFixAiNHjsT48eNx6NAhNG3aFB06dEBycnKR++/cuRM9e/bEjh07sG/fPvj4+KB9+/ZISEgo99rJ9ORqtPhw9VEs3n8FIstMfL0JBraurXRZRERkTOFm6tSpGDRoECIiItCwYUPMmjULDg4OmD9/fpH7L126FO+99x4CAgLg5+eHuXPnQqvVYtu2beVeO5mW7FwNhi47jLWHEmSH4Wk9AtArtLrSZRERkTH1ucnJyUFsbCzGjBmTv02lUslTTaJVpjgyMzOhVqvh5uZW5P3Z2dlyyZOamiq/iseIhZSR99obyjG4n6PB+78ewe7zt2BtaYHpPZqibQMPg6lPSYZ2rOjJeLyMB4+VfvR5nRQNNykpKdBoNPD09Cy0XazHxcUV6zk++eQTVK1aVQaiokyaNAkTJkx4ZPvmzZtlCxEpa8uWLUqXgKxcYE6cJS6kWcBGpUNkPQ1yLh3ExktKV2ZYDOFYUfHxeBkPHisUuzHDLEZLTZ48GcuXL5f9cERn5KKIViHRp6dgy01ePx1nZ+dyrJYeTuDiDd2uXTtYWys3L9OdzBxELjqEC2mpqGBrhbl9AxFUo6Ji9RgiQzlWVDw8XsaDx0o/eWdeDD7cuLu7w9LSEklJSYW2i3UvL68nPva7776T4Wbr1q3w9/d/7H62trZyeZj4ReIvk/KUPA7JaVnoOz8WZ5LSUNHBGosjQ9HY20WRWowB3zPGhcfLePBYFY8+r5GiHYptbGwQFBRUqDNwXufgsLCwxz5uypQp+Oqrr7Bp0yYEBweXU7VkSq7dyUT3WftksPFwssXKwWEMNkREJkLx01LilFF4eLgMKSEhIZg2bRoyMjLk6CmhX79+8Pb2ln1nhG+++Qbjxo3DsmXL5LVxEhMT5fYKFSrIhehpLqVkoPcv+3H9XhaqVbTHsoEtUL0S+18REZkKxcNNjx49cPPmTRlYRFARQ7xFi0xeJ+P4+Hg5girPzJkz5Sirbt26FXoecZ2cL774otzrJ+MSl5iKPnNjkJKejdqVHbF0YCiquNgrXRYREZlSuBGGDh0ql6KIzsIFXb58uZyqIlNz7Npd9Jsfg7uZajSo4ozFkSFwr/BofywiIjJuBhFuiMpazKXbGBB1AOnZuQjwccXCiBC4OLADHxGRKWK4IZO36+xNDF58EFlqLcJqV8Iv4cFy2DcREZkmfsKTSdt0IhH//vUQ1BodXvLzwM+9m8HO2lLpsoiIqAwx3JDJ+u3wNXy46hg0Wh06NamC//YIgI2V4tOpERFRGWO4IZO0NPoKxq47AZ0O6BZUDd+86S8nwyQiItPHcEMmZ87fFzBx44O5yfq3rIlxnRtCxWBDRGQ2GG7IZOh0Okzbeg4/bDsn1997oQ4+6lAfFhYMNkRE5oThhkwm2Hy94TTm7nkwlbcINe+/6Kt0WUREpACGGzJ6osOw6F/za0y8XP+iS0P0b1VL6bKIiEghDDdk1NQaLT5cdRTrj1yH6FYz+Q1/dG/uo3RZRESkIIYbMlrZuRoMXXYYW04lwUplgWlvB6Czf1WlyyIiIoUx3JBRyszJxeDFsdh9LkVeu2Zm72Z4ucGDyVaJiMi8MdyQ0UnNUiMy6gAOXL4DBxtLzO0XjJa+7kqXRUREBoLhhozKnYwcObP38YR7cLKzQlRECIJqVFS6LCIiMiAMN2Q0ktOy0HduDM4kpcHN0QaLBoSgsbeL0mUREZGBYbgho5Bw9z56/7Ifl29lwsPJFksHhqKup5PSZRERkQFiuCGDdyklA33mRsuA4+1qj2WDQlGjkqPSZRERkYFiuCGDdiYxDX3mReNmWjZquztiycBQVHW1V7osIiIyYAw3ZLCOXbsrOw/fzVTDz8sJiyNDUdnJVumyiIjIwDHckEE6cPk2IhYcQHp2Lpr6uGJhRHO4OtgoXRYRERkBhhsyOLvP3cSgRQeRpdYipJYb5vdvjgq2/FUlIqLi4V8MMihiKoX3lx5CjkaL5+tVxuw+QbC3sVS6LCIiMiIMN2Qwfj96HSNWHJGzfHdo5InpPQNha8VgQ0RE+mG4IYOw4kA8Rq89Dp0OeD3QG99284eVpUrpsoiIyAgx3JDi5u+5hC//PCVv9wqtjv/8qzFUKgulyyIiIiPFcEOKmrnrIqZuPS9vD2pdC5++2gAWFgw2RERUcgw3pAidToc/4lXYmvAg2HzQti6Gv1yXwYaIiJ4Zww2VO61Wh682nsHWhAd9aj57tQEGPV9b6bKIiMhEMNxQuRIjoUavOYZVsdfk+oQuDRDeisGGiIhKD8MNlRu1RiuHev957AZEf+GedTToFeKjdFlERGRiGG6oXGSpNRi67BC2nk6GtaUFpr7lD+2VWKXLIiIiE8QLiVCZy8zJxcCFB2WwsbVSYU7fYHRs5Kl0WUREZKLYckNlKjVLjQELDuDglTtwsLHE3PBgtKzjDrVarXRpRERkohhuqMzcychBv/kxOJ5wD052Vlg4IATNqldUuiwiIjJxDDdUJpLTstB3bgzOJKXBzdEGiwaEoLG3i9JlERGRGWC4oVKXcPc++syNxqWUDHg42WLZoFD4ejgpXRYREZkJhhsqVZdTMtB7brQMON6u9jLY1KjkqHRZRERkRhhuqNScS0qTwSY5LRu13R2xZGAoqrraK10WERGZGYYbKhUnEu6h77xo3MlUo76nkww2lZ1slS6LiIjMEMMNPbPYK3fQf0EM0rJy4V/NBQsjQlDR0UbpsoiIyEwx3NAz2XshRV6gLzNHg+Y1K2J+/+ZwsrNWuiwiIjJjDDdUYjvikjFkSSyyc7VoXdcds/sGwcGGv1JERKQs/iWiEvnf8RsYtvww1Bod2jbwxE+9AmFnbal0WURERAw3pL81sdfw0eqj0OqAzv5V8N8eAbC25DRlRERkGBhuSC9L9l/B2HUn5O23gqph8pv+sFRZKF0WERFRPoYbKra5uy/iPxtOy9vhYTUwvksjqBhsiIjIwDDc0FPpdDpM33Ye/916Vq4PaVMHn3SsDwsLBhsiIjI8DDf01GAzeVMcZu+6KNdHtauHoS/5MtgQEZHBYrihx9Jqdfjij5NYtO+KXB/bqQEGtq6tdFlERERPxHBDRdJodfhkzTGsjr0G0Ujz9WtN0Cu0utJlERERPRXDDT1CrdFixIoj+PPYDYj+wt93b4rXA6spXRYREVGxMNxQIVlqDYYuO4Stp5NhbWmB6W8H4pUmVZQui4iIqNgYbihfZk4uBi+Oxe5zKbC1UmFWnyC86OehdFlERER6YbghKS1LjQFRB3Dg8h042FhibngwWtZxV7osIiIivTHcEO5m5qDf/Bgcu3YPTnZWiIoIQVCNikqXRUREVCIMN2bev2bTiUT8tOM8zienw83RBosGhKCxt4vSpREREZWYQcx2OGPGDNSsWRN2dnYIDQ1FTEzME/dftWoV/Pz85P5NmjTBxo0by61WUyCCzFd/nkKLSdvwwYojcr2yky1WvNOCwYaIiIye4i03K1aswMiRIzFr1iwZbKZNm4YOHTrgzJkz8PB4tDPr3r170bNnT0yaNAmdO3fGsmXL8Nprr+HQoUNo3LixIj+DMbXSLIuJR8yl2/nbq7rYoUfz6vIaNiLgEBERGTvFw83UqVMxaNAgREREyHURcjZs2ID58+dj9OjRj+z/ww8/oGPHjvjoo4/k+ldffYUtW7bgp59+ko9VSnauBjfTsmFo7t1X47dDCVhz6BruZKrlNnHtmpf8PNEr1Adt6nlwVm8iIjIpioabnJwcxMbGYsyYMfnbVCoV2rZti3379hX5GLFdtPQUJFp61q1bV+T+2dnZcsmTmpoqv6rVarmUlqNX76L7nCefTlOal7MtugdVQ7cgb1RxsZPbtJpcaDXlX0vea1+ax4DKBo+VceHxMh48VvrR53VSNNykpKRAo9HA09Oz0HaxHhcXV+RjEhMTi9xfbC+KOH01YcKER7Zv3rwZDg4OKC2X0wBrC0sYGjF1Ql0XHVp66tDQNQOqrDM4/M8ZHIZhEK1uZBx4rIwLj5fx4LEqnszMTOM5LVXWRKtQwZYe0XLj4+OD9u3bw9nZuVS/13ul+mymn8DFG7pdu3awtrZWuhx6Ah4r48LjZTx4rPSTd+bF4MONu7s7LC0tkZSUVGi7WPfy8iryMWK7Pvvb2trK5WHiF4m/TMrjcTAePFbGhcfLePBYFY8+r5GiQ8FtbGwQFBSEbdu25W/TarVyPSwsrMjHiO0F9xdE8n3c/kRERGReFD8tJU4ZhYeHIzg4GCEhIXIoeEZGRv7oqX79+sHb21v2nRGGDx+ONm3a4Pvvv0enTp2wfPlyHDx4EHPmzFH4JyEiIiJDoHi46dGjB27evIlx48bJTsEBAQHYtGlTfqfh+Ph4OYIqT8uWLeW1bcaOHYtPP/0UdevWlSOleI0bIiIiMohwIwwdOlQuRdm5c+cj29566y25EBERERnk9AtEREREpYXhhoiIiEwKww0RERGZFIYbIiIiMikMN0RERGRSGG6IiIjIpDDcEBERkUlhuCEiIiKTwnBDREREJsUgrlBcnnQ6nd5Tp1PpU6vVyMzMlMeBs+EaNh4r48LjZTx4rPST93c77+/4k5hduElLS5NffXx8lC6FiIiISvB33MXF5Yn7WOiKE4FMiFarxfXr1+Hk5AQLCwulyzHrBC4C5tWrV+Hs7Kx0OfQEPFbGhcfLePBY6UfEFRFsqlatWmhC7aKYXcuNeEGqVaumdBn0f8Qbmm9q48BjZVx4vIwHj1XxPa3FJg87FBMREZFJYbghIiIik8JwQ4qwtbXF+PHj5VcybDxWxoXHy3jwWJUds+tQTERERKaNLTdERERkUhhuiIiIyKQw3BAREZFJYbghIiIik8JwQ8/k66+/RsuWLeHg4ABXV9ci94mPj0enTp3kPh4eHvjoo4+Qm5tbaJ+dO3eiWbNmctSAr68voqKiHnmeGTNmoGbNmrCzs0NoaChiYmIK3Z+VlYX3338flSpVQoUKFfDmm28iKSmplH9i8/O0152ezd9//40uXbrIq66Kq6avW7eu0P1izMe4ceNQpUoV2Nvbo23btjh37lyhfW7fvo3evXvLC8GJ92FkZCTS09ML7XPs2DG0bt1aHkdxVdwpU6Y8UsuqVavg5+cn92nSpAk2btxYRj+1cZo0aRKaN28ur3AvPstee+01nDlzRu/PofL6TDRrYrQUUUmNGzdON3XqVN3IkSN1Li4uj9yfm5ura9y4sa5t27a6w4cP6zZu3Khzd3fXjRkzJn+fixcv6hwcHORznDp1Svfjjz/qLC0tdZs2bcrfZ/ny5TobGxvd/PnzdSdPntQNGjRI5+rqqktKSsrfZ8iQITofHx/dtm3bdAcPHtS1aNFC17Jly3J4FUxXcV53ejbiPfHZZ5/p1q5dK0au6n777bdC90+ePFm+t9atW6c7evSormvXrrpatWrp7t+/n79Px44ddU2bNtXt379ft3v3bp2vr6+uZ8+e+fffu3dP5+npqevdu7fuxIkTul9//VVnb2+vmz17dv4+//zzj3zfTZkyRb4Px44dq7O2ttYdP368nF4Jw9ehQwfdggUL5Gt45MgR3auvvqqrXr26Lj09vdifQ+X5mWjOGG6oVIg3fFHhRrxxVSqVLjExMX/bzJkzdc7Ozrrs7Gy5/vHHH+saNWpU6HE9evSQHyR5QkJCdO+//37+ukaj0VWtWlU3adIkuX737l35Qbxq1ar8fU6fPi3/WOzbt6+Uf1rz8bTXnUrXw+FGq9XqvLy8dN9++23+NvG7bmtrKwOKIP74iccdOHAgf5///e9/OgsLC11CQoJc//nnn3UVK1bMf88Jn3zyia5+/fr56927d9d16tSpUD2hoaG6wYMHl9FPa/ySk5Pla79r165ifw6V12eiueNpKSpT+/btk83bnp6e+ds6dOggJ4w7efJk/j6iqb0gsY/YLuTk5CA2NrbQPmKOMLGet4+4X61WF9pHNK9Xr149fx/ST3Fedypbly5dQmJiYqFjIObWEacg8o6B+CpORQUHB+fvI/YXxyo6Ojp/n+effx42NjaF3mPilMqdO3eK9T6kR927d09+dXNzK/bnUHl9Jpo7hhsqU+KDueCbWMhbF/c9aR/xZr9//z5SUlKg0WiK3Kfgc4gP7of7/RTch/RTnNedylbe6/y0333Rb6MgKysr+Qf3ae+xgt/jcfvwWBdNq9Xigw8+QKtWrdC4ceNifw6V12eiuWO4oUeMHj1admx80hIXF6d0mUREihGdhk+cOIHly5crXQoVwaqojWTeRo0ahf79+z9xn9q1axfruby8vB7pwZ83ckDcl/f14dEEYl2M/BCjQywtLeVS1D4Fn0M01d69e7fQ/5oK7kP6cXd3f+rrTmUr73UWr7kYLZVHrAcEBOTvk5ycXOhxYuSNGEH1tPdYwe/xuH14rB81dOhQ/Pnnn3KkW7Vq1fK3F+dzqLw+E80dW27oEZUrV5bniZ+0FDx3/yRhYWE4fvx4oQ/fLVu2yDdpw4YN8/fZtm1boceJfcR2QXyvoKCgQvuIJmGxnrePuN/a2rrQPqI/gRhymbcP6ac4rzuVrVq1ask/VgWPgTg1IfrS5B0D8VX8MRV9MPJs375dHivRNydvH/GHWPQHKfgeq1+/PipWrFis9yE9GJYvgs1vv/0mX2NxfAoqzudQeX0mmj2lezSTcbty5YoczjhhwgRdhQoV5G2xpKWlFRr22L59ezl0UgxlrFy5cpHDHj/66CM5smDGjBlFDnsUI0SioqLk6JB33nlHDnssOOJADMEUwzK3b98uh2CGhYXJhUquOK87PRvxXsl734iPZHFpBXFbvLfyhoKL13z9+vW6Y8eO6f71r38VORQ8MDBQFx0drduzZ4+ubt26hYaCi1E8Yih437595TBmcVzFe+7hoeBWVla67777Tr4Px48fz6HgD3n33XflqNCdO3fqbty4kb9kZmYW+3OoPD8TzRnDDT2T8PBw+YH88LJjx478fS5fvqx75ZVX5HU1xPUcRo0apVOr1YWeR+wfEBAgr9tQu3ZtObT8YeJaD+JDQ+wjhkGKa3oUJD7s33vvPTnkVXwwvP766/KDh57N0153ejbid7+o95B4b+UNB//8889lOBF/zF5++WXdmTNnCj3HrVu3ZJgR/8EQQ4ojIiLy/4ORR1wj57nnnpPP4e3tLUPTw1auXKmrV6+ePNZiKPKGDRvK+Kc3LkUdJ7EU/LwqzudQeX0mmjML8Y/SrUdEREREpYV9boiIiMikMNwQERGRSWG4ISIiIpPCcENEREQmheGGiIiITArDDREREZkUhhsiIiIyKQw3REREZFIYboiISskLL7wACwsLuRw5cqTIfS5fvpy/T97kl0RUuhhuiOiJxAzxr7322iPbd+7cKf9Ai0kbS0txnzNvP7GoVCq4uLggMDAQH3/8MW7cuKH3961ZsyamTZuG0jBo0CBZQ+PGjQuFmbyw4+PjI+8fNWpUqXw/InoUww0RGS0x4/L169dx4MABfPLJJ9i6dasMFWLWZaU4ODjImbytrKyKvN/S0lLeX6FChXKvjchcMNwQUanZs2cPWrduDXt7e9lCMWzYMGRkZOTfv3jxYgQHB8PJyUn+ge/VqxeSk5PzWzhefPFFebtixYqytUO0Gj2Jh4eHfJ569erh7bffxj///IPKlSvj3XffLXSq6IMPPij0ONESlffc4v4rV65gxIgR+a1BomZnZ2esXr260OPWrVsHR0dHpKWllcKrRURlheGGiErFhQsX0LFjR7z55ps4duwYVqxYIcPO0KFD8/dRq9X46quvcPToURkURKDJCxkiDK1Zsya/RUacuvnhhx/0qkGEqiFDhsiQkxeanmbt2rWoVq0avvzyS/k9xSICjAhLCxYsKLSvWO/WrZsMZ0RkuIpuNyUiKuDPP/985DSKRqMptD5p0iT07t07v5Wkbt26mD59Otq0aYOZM2fCzs4OAwYMyN+/du3a8v7mzZsjPT1dPr+bm1t+i4yrq2uJavXz85NfRXASz/M04nuKU0V5rUl5Bg4ciJYtW8qwU6VKFRmWNm7cKE99EZFhY8sNET2VOF0kOsQWXObOnVtoH9EaExUVJUNK3tKhQwdotVpcunRJ7hMbG4suXbqgevXqMkyI4CPEx8eXWq06nU5+FaeXnkVISAgaNWqEhQsXyvUlS5agRo0aeP7550ulTiIqO2y5IaKnEqdpfH19C227du1aoXXR+jJ48GDZz+ZhIsyIfiwi7Ihl6dKlsm+MCDViPScnp9RqPX36dP4IKEGMpsoLPAVPjxWHaL2ZMWMGRo8eLU9JRUREPHNoIqKyx3BDRKWiWbNmOHXq1CMhKI8YwXTr1i1MnjxZ9q8RDh48WGgfGxubIk95Fdf9+/cxZ84c2boiwpMgvhYcHi6e+8SJE/mdl/O+b1Hfs0+fPnJ4uTh9Jn628PDwEtVFROWLp6WIqFSIodh79+6VHYjFaatz585h/fr1+R2KReuNCBE//vgjLl68iN9//112Li5InPYRLSOij8/Nmzdla9CTiH4wiYmJ8nstX74crVq1QkpKiuzjk+ell17Chg0b5BIXFydHUj18HR3RyvP3338jISFBPj6PGLX1xhtv4KOPPkL79u1lx2MiMnwMN0RUKvz9/bFr1y6cPXtWDgcXF9UbN24cqlatmt+CIvrkrFq1Cg0bNpQtON99912h5/D29saECRPkaSBPT89CI62KUr9+ffn8QUFB8vnatm0rW2XE8+cRnZhFi0u/fv1kHx/Rkblgq40gRkqJDsh16tTJb/HJExkZKU+bFewMrQ/R50h43HVviKj0WegePhlNRESFrs0jroEjLhaYd9rsccQ1c8SUCgWvdrx//36EhYXJlih3d/f87V988YUcDv+4aRqIqOTYckNEVITMzEx57R7RIiQ6Sj8t2OT5+eef5Ugx0cfo/Pnz+Pbbb9G0adP8YCM6UYv7J06cWMY/AZH5YssNEVERRMvK119/LTsni75DxZkuQfTZEZ2ahdu3b+e35MyaNUuethNyc3PlKTDB1tY2v3M1EZUehhsiIiIyKTwtRURERCaF4YaIiIhMCsMNERERmRSGGyIiIjIpDDdERERkUhhuiIiIyKQw3BAREZFJYbghIiIimJL/B2d8m7s0QfnEAAAAAElFTkSuQmCC" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", + "Q = []\n", + "V = []\n", + "\n", + "for duty in np.linspace(-17000, 25000, 50):\n", + " # fix the heat duty\n", + " m.fs.flash.heat_duty.fix(duty)\n", + "\n", + " # append the value of the duty to the Q list\n", + " Q.append(duty)\n", + "\n", + " # print the current simulation\n", + " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", + "\n", + " # solve the model\n", + " status = solver.solve(m)\n", + "\n", + " # append the value for vapor fraction if the solve was successful\n", + " if solve_successful(status):\n", + " V.append(value(m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]))\n", + " print(\"... solve successful.\")\n", + " else:\n", + " V.append(0.0)\n", + " print(\"... solve failed.\")\n", + "\n", + "plt.figure(\"Purity\")\n", + "plt.plot(Q, V)\n", + "plt.grid()\n", + "plt.xlabel(\"Heat Duty [J]\")\n", + "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", + "plt.show()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", + "\n", + "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", + "\n", + "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", + "\n" ] - }, - "metadata": { - "filenames": { - "image/png": "C:\\Users\\dkgun\\src\\dangunter\\examples\\idaes_examples\\notebooks\\_build\\jupyter_execute\\docs\\tut\\core\\flash_unit_doc_35_51.png" - } - }, - "output_type": "display_data" - } - ], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", - "Q = []\n", - "V = []\n", - "\n", - "for duty in np.linspace(-17000, 25000, 50):\n", - " # fix the heat duty\n", - " m.fs.flash.heat_duty.fix(duty)\n", - "\n", - " # append the value of the duty to the Q list\n", - " Q.append(duty)\n", - "\n", - " # print the current simulation\n", - " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", - "\n", - " # solve the model\n", - " status = solver.solve(m)\n", - "\n", - " # append the value for vapor fraction if the solve was successful\n", - " if solve_successful(status):\n", - " V.append(value(m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]))\n", - " print(\"... solve successful.\")\n", - " else:\n", - " V.append(0.0)\n", - " print(\"... solve failed.\")\n", - "\n", - "plt.figure(\"Purity\")\n", - "plt.plot(Q, V)\n", - "plt.grid()\n", - "plt.xlabel(\"Heat Duty [J]\")\n", - "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", - "\n", - "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", - "\n", - "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: \n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 137\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 72\n", - "\n", - "Total number of variables............................: 42\n", - " variables with only lower bounds: 3\n", - " variables with lower and upper bounds: 10\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 42\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", - " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", - " 3 0.0000000e+00 6.95e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 3\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 8.9144743362344083e-11 6.9545421865768731e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 8.9144743362344083e-11 6.9545421865768731e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 4\n", - "Number of objective gradient evaluations = 4\n", - "Number of equality constraint evaluations = 4\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 4\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 3\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n", - "\b\b\b\b\b\b\b\b\b\b\b\b\b\b" - ] }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.flash Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 5083.6 : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol mole / second 1.0000 0.54833 0.45167 \n", - " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", - " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", - " temperature kelvin 368.00 369.07 369.07 \n", - " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", - "====================================================================================\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, + "tags": [ + "solution" + ] + }, + "cell_type": "code", + "source": [ + "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", + "m.fs.flash.heat_duty.fix(0)\n", + "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "\n", + "# Unfix the heat_duty variable\n", + "m.fs.flash.heat_duty.unfix()\n", + "\n", + "# Todo: Add a new constraint (benzene mole fraction to 0.6)\n", + "m.benz_purity_con = Constraint(\n", + " expr=m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"] == 0.6\n", + ")\n", + "\n", + "# solve the problem\n", + "status = solver.solve(m, tee=True)\n", + "\n", + "# Check stream condition\n", + "m.fs.flash.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" } - ], - "source": [ - "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", - "m.fs.flash.heat_duty.fix(0)\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", - "\n", - "# Unfix the heat_duty variable\n", - "m.fs.flash.heat_duty.unfix()\n", - "\n", - "# Todo: Add a new constraint (benzene mole fraction to 0.6)\n", - "m.benz_purity_con = Constraint(\n", - " expr=m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"] == 0.6\n", - ")\n", - "\n", - "# solve the problem\n", - "status = solver.solve(m, tee=True)\n", - "\n", - "# Check stream condition\n", - "m.fs.flash.report()" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 3 -} + "nbformat": 4, + "nbformat_minor": 3 +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 19e3b691..7c93163d 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,27 +141,29 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -144,34 +174,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -186,7 +226,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -195,40 +235,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", + "\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -236,24 +419,32 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -262,22 +453,26 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -314,7 +509,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -322,24 +527,40 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -348,51 +569,79 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -400,25 +649,29 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -438,10 +691,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -451,34 +707,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -490,22 +801,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -513,14 +837,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -533,22 +855,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -556,7 +878,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -564,11 +886,17 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -577,28 +905,36 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -606,14 +942,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -629,7 +967,106 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 } ], "metadata": { @@ -654,4 +1091,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 6b4b3752..0e823872 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,36 +527,52 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -359,7 +609,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -367,30 +627,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -402,11 +668,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -415,79 +695,147 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -495,42 +843,120 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -550,10 +976,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -563,34 +992,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -602,22 +1086,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -625,14 +1122,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -645,22 +1140,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -668,7 +1163,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -676,18 +1171,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -700,7 +1198,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -731,11 +1229,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -744,27 +1475,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -797,18 +1528,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -816,14 +1776,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -839,17 +1801,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -868,7 +1931,102 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 } ], "metadata": { @@ -893,4 +2051,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 562af431..62609b47 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,50 +110,64 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Use the pprint method on the model, i.e. m.pprint(), to see what is currently contained in the model.\n", - "
" - ] + ], + "outputs": [], + "execution_count": 3 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -145,34 +178,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -187,7 +230,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -196,105 +239,249 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, - "metadata": {}, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", "outputs": [], - "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" - ] + "execution_count": 9 }, { + "metadata": {}, "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", "\n", "
\n", "Inline Exercise:\n", - "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, "cell_type": "code", - "execution_count": 10, + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { "metadata": { - "tags": [ - "solution" - ] + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "" + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "## 4 Set Operating Conditions\n", "\n", - "# Todo: Call the python help on the degrees_of_freedom function\n", - "help(degrees_of_freedom)" + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", + "\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "
\n", - "Inline Exercise:\n", - "Now print the degrees of freedom for your model. The result should be 7.\n", - "
" + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", + "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, + "tags": [ + "solution" + ] + }, "cell_type": "code", - "execution_count": 12, + "source": [ + "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Todo: Call the python help on the degrees_of_freedom function\n", + "help(degrees_of_freedom)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 + }, + { "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "code", - "execution_count": 13, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.334804Z", + "start_time": "2025-06-06T16:45:50.327991Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 7" - ] + ], + "outputs": [], + "execution_count": 19 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -331,22 +518,20 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Write the code below to specify the inlet conditions and unit specifications described above\n", - "
" + "\n" ] }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -358,124 +543,242 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" - ] + ], + "outputs": [], + "execution_count": 21 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "
\n", - "Inline Exercise:\n", - "Check the degrees of freedom again to ensure that the system is now square. You should see that the degrees of freedom is now 0.\n", - "
" + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "code", - "execution_count": 18, "metadata": { "tags": [ "testing" ] }, + "cell_type": "code", "outputs": [], + "execution_count": 24, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", - "
\n", - "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", - "
" + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" ] }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", - "
\n", - "Inline Exercise:\n", - "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", - "
" + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" ] }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "code", - "execution_count": 23, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.975773Z", + "start_time": "2025-06-06T17:04:32.972754Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ - "# Check for optimal solution\n", + "# Check for an optimal solution\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert status.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 38 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -495,10 +798,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -508,38 +814,95 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "code", - "execution_count": 26, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:39.229802Z", + "start_time": "2025-06-06T17:04:39.132903Z" + }, "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check optimal solution values\n", "import pytest\n", @@ -563,13 +926,15 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(368, abs=1e-3)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 41 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -581,38 +946,38 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", - "
" + "\n" ] }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -625,7 +990,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -656,27 +1021,248 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Repeat the exercise above, but create a figure showing the heat duty vs. the mole fraction of Benzene in the vapor outlet. Remove any unnecessary printing to create cleaner results.\n", - "
" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -709,33 +1295,250 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", - "
\n" + "\n" ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -754,17 +1557,110 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Check for solver status\n", "assert status.solver.termination_condition == TerminationCondition.optimal\n", @@ -789,7 +1685,9 @@ ")\n", "assert value(m.fs.flash.vap_outlet.temperature[0]) == pytest.approx(369.07, abs=1e-2)\n", "assert value(m.fs.flash.vap_outlet.pressure[0]) == pytest.approx(101325, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": null } ], "metadata": { @@ -814,4 +1712,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 6b4b3752..0e823872 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-06T16:45:45.923673Z", + "start_time": "2025-06-06T16:45:45.919855Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,37 +25,46 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "# Flash Unit Model\n", + "# Flash Unit Model Tutorial\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Andrew Lee \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", - "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene. The inlet specifications for this flash tank are:\n", + "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "Inlet Specifications:\n", - "* Mole fraction (Benzene) = 0.5\n", - "* Mole fraction (Toluene) = 0.5\n", - "* Pressure = 101325 Pa\n", - "* Temperature = 368 K\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", "\n", - "We will complete the following tasks:\n", - "* Create the model and the IDAES Flowsheet object\n", - "* Import the appropriate property packages\n", - "* Create the flash unit and set the operating conditions\n", - "* Initialize the model and simulate the system\n", - "* Demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", - "\n", - "## Create the Model and the IDAES Flowsheet\n", + "* General Workflow: https://idaes-pse.readthedocs.io/en/stable/how_to_guides/workflow/general.html\n", + "* Flash Unit Model Documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 1 Import Modules\n", "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", @@ -66,23 +77,31 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.094293Z", + "start_time": "2025-06-06T16:45:45.938076Z" + } + }, "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], "source": [ "from pyomo.environ import ConcreteModel, SolverFactory, Constraint, value\n", "from idaes.core import FlowsheetBlock\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog" - ] + "import idaes.logger as idaeslog\n", + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 2 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "In the next cell, we will create the `ConcreteModel` and the `FlowsheetBlock`, and attach the flowsheet block to the Pyomo model.\n", + "## 2 Create the Model and IDAES Flowsheet\n", + "\n", + "In the next cell, we will create the `ConcreteModel` object often named `m` (which comes from Pyomo) and then connect the `FlowsheetBlock` (which comes from IDAES) to `m`. We ensure `dynamic=False` since this is a steady-state problem. This creates our overall model and adds the flowsheet capabilities that IDAES provides to the Pyomo model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -91,20 +110,29 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.521103Z", + "start_time": "2025-06-06T16:45:49.517229Z" + } + }, "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 3 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ - "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block.\n", + "At this point, we have a single Pyomo model that contains an (almost) empty flowsheet block. Lets use the `m.pprint()` to investigate the current contents of the model.\n", "\n", "
\n", "Inline Exercise:\n", @@ -113,41 +141,64 @@ ] }, { - "cell_type": "code", - "execution_count": 3, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.531374Z", + "start_time": "2025-06-06T16:45:49.527521Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: call pprint on the model", "outputs": [], - "source": [ - "# Todo: call pprint on the model" - ] + "execution_count": 4 }, { - "cell_type": "code", - "execution_count": 4, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.577500Z", + "start_time": "2025-06-06T16:45:49.572256Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: call pprint on the model\n", "m.pprint()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Block Declarations\n", + " fs : Size=1, Index=None, Active=True\n", + " 1 Set Declarations\n", + " _time : Size=1, Index=None, Ordered=Insertion\n", + " Key : Dimen : Domain : Size : Members\n", + " None : 1 : Any : 1 : {0.0,}\n", + "\n", + " 1 Declarations: _time\n", + "\n", + "1 Declarations: fs\n" + ] + } + ], + "execution_count": 5 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Define Properties\n", + "### 2.1 Define Properties\n", "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that allow for specification of the fluid using any set of valid state variables (e.g., component molar flows vs overall flow and mole fractions). This flexibility is designed to support advanced modeling needs that may rely on specific formulations. To learn about creating your own property package, please consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/components/property_package/index.html and look at examples within IDAES\n", + "IDAES also supports creation of your own property packages that will be shown in a later module.\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -158,34 +209,44 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.649106Z", + "start_time": "2025-06-06T16:45:49.626357Z" + } + }, "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], "source": [ "from idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE import (\n", " BTXParameterBlock,\n", ")" - ] + ], + "outputs": [], + "execution_count": 6 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.669359Z", + "start_time": "2025-06-06T16:45:49.657658Z" + } + }, "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], "source": [ "m.fs.properties = BTXParameterBlock(\n", " valid_phase=(\"Liq\", \"Vap\"), activity_coeff_model=\"Ideal\", state_vars=\"FTPz\"\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Adding Flash Unit\n", + "### 2.2 Adding Flash Unit\n", "\n", - "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet. \n", + "Now that we have the flowsheet and the properties defined, we can create the flash unit and add it to the flowsheet.\n", "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", @@ -200,7 +261,7 @@ "* Pressure changing equipment (compressors, expanders, pumps)\n", "* Feed and Product (source / sink) components\n", "\n", - "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash is the one we created earlier.\n", + "In this module, we will import the `Flash` unit model from `idaes.models.unit_models` and create an instance of the flash unit, attaching it to the flowsheet. Each IDAES unit model has several configurable options to customize the model behavior, but also includes defaults for these options. In this example, we will specify that the property package to be used with the Flash unit model is the one we created earlier by setting `property_package=m.fs.properties` within the `Flash` method.\n", "\n", "
\n", "Inline Exercise:\n", @@ -209,40 +270,183 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.749283Z", + "start_time": "2025-06-06T16:45:49.678730Z" + } + }, "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "source": "from idaes.models.unit_models import Flash", "outputs": [], - "source": [ - "from idaes.models.unit_models import Flash" - ] + "execution_count": 8 }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.772441Z", + "start_time": "2025-06-06T16:45:49.758167Z" + } + }, "cell_type": "code", - "execution_count": 8, + "source": "m.fs.flash = Flash(property_package=m.fs.properties)", + "outputs": [], + "execution_count": 9 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.783706Z", + "start_time": "2025-06-06T16:45:49.781688Z" + }, + "tags": [ + "noauto" + ] + }, + "cell_type": "code", + "source": "m.pprint()", "outputs": [], + "execution_count": 10 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "m.fs.flash = Flash(property_package=m.fs.properties)" + "## 3 Scaling the Model\n", + "\n", + "Now that the model is built, with properties set and the unit model created and added to the flowsheet, the next step is to scale the model. Ensuring that a model is well scaled is important for increasing the efficiency and reliability of solvers, and users should consider model scaling as an integral part of the modeling process. IDAES provides a number of tool for assisting users with scaling their models, and details on these can be found at https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html#scaling-toolbox\n", + "\n", + "There are currently two primary methods in scaling the model: manual scaling of each relevant component, or utilizing the AutoScaler Class. The more careful and risk-free method of manually scaling each component is the recommended method for maximum control and assurance that the model will be well-scaled. This comes with the drawback of being more meticulous while the AutoScaler is much simpler to use since it scaled the whole model all at once, it is less precise by lacking direct control over the scaling factor for each component and relying on scaling factors to be estimated. Both methods will be shown below" ] }, { + "metadata": {}, "cell_type": "markdown", + "source": [ + "### 3.1 Manual Scaling\n", + "The `set_scaling_factor` function is imported from `idaes.core.scaling.util` and is called with and used on each relevant component that needs to be well scaled. The component is the first argument and its scaling factor is the second argument.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `set_scaling_factor` and set the scaling factor for both temperature and pressure\n", + "
\n", + "\n", + "Both `temperature` and `pressure` can be found at `m.fs.flash.inlet`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.795252Z", + "start_time": "2025-06-06T16:45:49.792075Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.util import set_scaling_factor", + "outputs": [], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.809330Z", + "start_time": "2025-06-06T16:45:49.806174Z" + } + }, + "cell_type": "code", + "source": [ + "set_scaling_factor(m.fs.flash.inlet.temperature, 300)\n", + "set_scaling_factor(m.fs.flash.inlet.pressure, 1e6)" + ], + "outputs": [], + "execution_count": 12 + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "At this point, we have created a flowsheet and a properties block. We have also created a flash unit and added it to the flowsheet. Under the hood, IDAES has created the required state variables and model equations. Everything is open. You can see these variables and equations by calling the Pyomo method `pprint` on the model, flowsheet, or flash tank objects. Note that this output is very exhaustive, and is not intended to provide any summary information about the model, but rather a complete picture of all of the variables and equations in the model." + "### 3.2 Scaling with AutoScaler\n", + "The `AutoScaler` class is imported from `idaes.core.scaling.autoscaling` and an instance of the class is created. This instance contains the method `scale_model` which is used to scale the whole model at once. This can be a useful option but is generally more risky than manually scaling the model components since it has less direct control and specification.\n", + "\n", + "
\n", + "Inline Exercise:\n", + "Execute the following two cells to import the `AutoScaler` class and create an autoscaler instance that scaled the whole model at once\n", + "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:49.826276Z", + "start_time": "2025-06-06T16:45:49.823030Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.scaling.autoscaling import AutoScaler", + "outputs": [], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.217776Z", + "start_time": "2025-06-06T16:45:49.836920Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [], + "execution_count": 14 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "" + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "## Set Operating Conditions\n", + "## 4 Set Operating Conditions\n", "\n", - "Now that we have created our unit model, we can specify the necessary operating conditions. It is often very useful to determine the degrees of freedom before we specify any conditions.\n", + "Now that we have created our unit model and scaled it, we can specify the necessary operating conditions. The inlet specifications for this flash tank are:\n", "\n", - "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n", + "Inlet Specifications:\n", + "* Mole fraction (Benzene) = 0.5\n", + "* Mole fraction (Toluene) = 0.5\n", + "* Pressure = 101325 Pa\n", + "* Temperature = 368 K\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 4.1 Degrees of Freedom\n", + "\n", + "It is often very useful to first determine the degrees of freedom before we specify any conditions.\n", "\n", + "The `idaes.core.util.model_statistics` package has a function `degrees_of_freedom`. To see how to use this function, we can make use of the Python function `help(func)`. This function prints the appropriate documentation string for the function.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Import the degrees_of_freedom function and print the help for the function by calling the Python help function.\n", @@ -250,41 +454,71 @@ ] }, { - "cell_type": "code", - "execution_count": 9, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.224457Z", + "start_time": "2025-06-06T16:45:50.221905Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function" - ] + ], + "outputs": [], + "execution_count": 15 }, { - "cell_type": "code", - "execution_count": 10, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.240605Z", + "start_time": "2025-06-06T16:45:50.237594Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: import the degrees_of_freedom function from the idaes.core.util.model_statistics package\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", "\n", "# Todo: Call the python help on the degrees_of_freedom function\n", "help(degrees_of_freedom)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function degrees_of_freedom in module idaes.core.util.model_statistics:\n", + "\n", + "degrees_of_freedom(block)\n", + " Method to return the degrees of freedom of a model.\n", + "\n", + " Args:\n", + " block : model to be studied\n", + "\n", + " Returns:\n", + " Number of degrees of freedom in block.\n", + "\n" + ] + } + ], + "execution_count": 16 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -293,36 +527,52 @@ ] }, { - "cell_type": "code", - "execution_count": 11, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.271361Z", + "start_time": "2025-06-06T16:45:50.268763Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: print the degrees of freedom for your model", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 17 }, { - "cell_type": "code", - "execution_count": 12, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.297399Z", + "start_time": "2025-06-06T16:45:50.291352Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 7\n" + ] + } + ], + "execution_count": 18 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ + "### 4.2 Specify Inlet Conditions\n", + "\n", "To satisfy our degrees of freedom, we will first specify the inlet conditions. We can specify these values through the `inlet` port of the flash unit.\n", "\n", "**To see the list of naming conventions for variables within the IDAES framework, consult the online documentation at: https://idaes-pse.readthedocs.io/en/stable/explanations/conventions.html#standard-naming-format**\n", @@ -359,7 +609,17 @@ "* inlet mole fraction (toluene) = 0.5 (`mole_frac_comp[0, \"toluene\"]`)\n", "* The heat duty on the flash set to 0 (`heat_duty`)\n", "* The pressure drop across the flash tank set to 0 (`deltaP`)\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Write the code below to specify the inlet conditions and unit specifications described above\n", @@ -367,30 +627,36 @@ ] }, { - "cell_type": "code", - "execution_count": 14, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.360852Z", + "start_time": "2025-06-06T16:45:50.357341Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "\n", "\n", "# Todo: Add 2 flash unit specifications given above" - ] + ], + "outputs": [], + "execution_count": 20 }, { - "cell_type": "code", - "execution_count": 15, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.396800Z", + "start_time": "2025-06-06T16:45:50.392314Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: Add inlet specifications given above\n", "m.fs.flash.inlet.flow_mol.fix(1)\n", @@ -402,11 +668,25 @@ "# Todo: Add 2 flash unit specifications given above\n", "m.fs.flash.heat_duty.fix(0)\n", "m.fs.flash.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "\n" ] }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -415,79 +695,147 @@ ] }, { - "cell_type": "code", - "execution_count": 16, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", "outputs": [], - "source": [ - "# Todo: print the degrees of freedom for your model" - ] + "execution_count": 22, + "source": "# Todo: print the degrees of freedom for your model" }, { - "cell_type": "code", - "execution_count": 17, "metadata": { "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Degrees of Freedom = 0\n" + ] + } + ], + "execution_count": 23, "source": [ "# Todo: print the degrees of freedom for your model\n", "print(\"Degrees of Freedom =\", degrees_of_freedom(m))" ] }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Initializing the Model\n", + "## 5 Initializing the Model\n", "\n", - "IDAES includes pre-written initialization routines for all unit models. You can call this initialize method on the units. In the next module, we will demonstrate the use of a sequential modular solve cycle to initialize flowsheets.\n", + "Now that all building steps are complete, the last step before solving the model is to initialize the model, or prepping the solve by giving it a good starting point. This is essentially giving the solver an initial guess for the iterative solver to reach convergence and is essential for both a fast and accurate solution. In IDAES, the current standard for initializing the model is by utilizing initializer instances. These initializer instances contain the initialize method that can be applied to any model type. For more information on initializing in IDAES, visit https://idaes-pse.readthedocs.io/en/stable/reference_guides/initialization/index.html.
\n", "\n", + "For this tutorial, we will import the initializer class `BlockTriangularizationInitializer` class from the `default_initializer` method from the flash unit model. This is often the simplest way to obtain a compatible initializer for each unit model, but you can also directly important any initializer needed from this source `idaes.core.initialization`. Each initializer instance contains the `initialize()` method that requires an argument to be initialized and in this case its the flash unit model.\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Call the initialize method on the flash unit to initialize the model.\n", + "Define the initializer instance, and initialize the flash unit model\n", "
" ] }, { - "cell_type": "code", - "execution_count": 19, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:45:50.499945Z", + "start_time": "2025-06-06T16:45:50.497439Z" + }, "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: initialize the flash unit", "outputs": [], - "source": [ - "# Todo: initialize the flash unit" - ] + "execution_count": 25 }, { - "cell_type": "code", - "execution_count": 20, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T16:51:40.247234Z", + "start_time": "2025-06-06T16:51:39.730044Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: initialize the flash unit\n", - "m.fs.flash.initialize(outlvl=idaeslog.INFO)" - ] + "FlashInitializer = m.fs.flash.default_initializer()\n", + "FlashInitializer.initialize(m.fs.flash)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:39 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 10:51:40 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 }, { + "metadata": {}, "cell_type": "markdown", + "source": "Another option for initializing is utilizing the default initializer that is attached to the unit model. Each unit model as a default initializer that is hypothetically the most compatible. It can be called with `m.fs.flash.initialize()`. While this is an option, it is generally preferred to import an initializer object and initialize the model with that to ensure more control over the initialization." + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ - "Now that the model has been defined and initialized, we can solve the model.\n", + "## 6 Solving the Model\n", "\n", + "Now that the model has been defined and initialized, we can solve the model.\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using the notation described in the previous model, create an instance of the \"ipopt\" solver and use it to solve the model. Set the tee option to True to see the log output.\n", @@ -495,42 +843,120 @@ ] }, { - "cell_type": "code", - "execution_count": 21, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.219172Z", + "start_time": "2025-06-06T17:04:32.216161Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "\n", "# Todo: solve the model" - ] + ], + "outputs": [], + "execution_count": 36 }, { - "cell_type": "code", - "execution_count": 22, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:32.439966Z", + "start_time": "2025-06-06T17:04:32.396984Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: create the ipopt solver\n", "solver = SolverFactory(\"ipopt\")\n", "\n", "# Todo: solve the model\n", "status = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 135\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 41\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 6.22e-05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e-11 1.00e-02 -1.0 6.22e-05 - 9.90e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0417014662014577e-12 1.4551915228366852e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 1\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 37 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Viewing the Results\n", + "## 7 Viewing the Results\n", "\n", "Once a model is solved, the values returned by the solver are loaded into the model object itself. We can access the value of any variable in the model with the `value` function. For example:\n", "```python\n", @@ -550,10 +976,13 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:35.556815Z", + "start_time": "2025-06-06T17:04:35.551070Z" + } + }, "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], "source": [ "# Print the pressure of the flash vapor outlet\n", "print(\"Pressure =\", value(m.fs.flash.vap_outlet.pressure[0]))\n", @@ -563,34 +992,89 @@ "# Call display on vap_outlet and liq_outlet of the flash\n", "m.fs.flash.vap_outlet.display()\n", "m.fs.flash.liq_outlet.display()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pressure = 101325.0\n", + "\n", + "Output from display:\n", + "vap_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.3961181748774193}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.633976648508129, (0.0, 'toluene'): 0.366023351491871}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n", + "liq_outlet : Size=1\n", + " Key : Name : Value\n", + " None : flow_mol : {0.0: 0.6038818251225807}\n", + " : mole_frac_comp : {(0.0, 'benzene'): 0.41211759772293044, (0.0, 'toluene'): 0.5878824022770694}\n", + " : pressure : {0.0: 101325.0}\n", + " : temperature : {0.0: 368.0}\n" + ] + } + ], + "execution_count": 39 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "The output from `display` is quite exhaustive and not really intended to provide quick summary information. Because Pyomo is built on Python, there are opportunities to format the output any way we like. Most IDAES models have a `report` method which provides a summary of the results for the model.\n", "\n", "
\n", "Inline Exercise:\n", - "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports. \n", + "Execute the cell below which uses the function above to print a summary of the key variables in the flash model, including the inlet, the vapor, and the liquid ports.\n", "
" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:38.727731Z", + "start_time": "2025-06-06T17:04:38.712131Z" + } + }, "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.flash.report()" - ] + "source": "m.fs.flash.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 0.0000 : watt : True : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.39612 0.60388 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.63398 0.41212 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.36602 0.58788 \n", + " temperature kelvin 368.00 368.00 368.00 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 40 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ - "## Studying Purity as a Function of Heat Duty\n", + "## Exercise: Studying Purity as a Function of Heat Duty\n", "\n", "Since the entire modeling framework is built upon Python, it includes a complete programming environment for whatever analysis we may want to perform. In this next exercise, we will make use of what we learned in this and the previous module to generate a figure showing some output variables as a function of the heat duty in the flash tank.\n", "\n", @@ -602,22 +1086,35 @@ ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:04:43.426680Z", + "start_time": "2025-06-06T17:04:43.423025Z" + } + }, "cell_type": "code", - "execution_count": 27, - "metadata": {}, + "source": "import matplotlib.pyplot as plt", "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] + "execution_count": 42 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Exercise specifications:\n", "* Generate a figure showing the flash tank heat duty (`m.fs.flash.heat_duty[0]`) vs. the vapor flowrate (`m.fs.flash.vap_outlet.flow_mol[0]`)\n", "* Specify the heat duty from -17000 to 25000 over 50 steps\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Using what you have learned so far, fill in the missing code below to generate the figure specified above. (Hint: import numpy and use the linspace function from the previous module)\n", @@ -625,14 +1122,12 @@ ] }, { - "cell_type": "code", - "execution_count": 29, "metadata": { "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -645,22 +1140,22 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "UnitModelInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "\n", " # fix the heat duty\n", " m.fs.flash.heat_duty.fix(duty)\n", - " \n", + "\n", " # append the value of the duty to the Q list\n", " Q.append(duty)\n", - " \n", + "\n", " # print the current simulation\n", " print(\"Simulating with Q = \", value(m.fs.flash.heat_duty[0]))\n", "\n", " # Solve the model\n", " status = solver.solve(m)\n", - " \n", + "\n", " # append the value for vapor fraction if the solve was successful\n", " if solve_successful(status):\n", " V.append(value(m.fs.flash.vap_outlet.flow_mol[0]))\n", @@ -668,7 +1163,7 @@ " else:\n", " V.append(0.0)\n", " print('... solve failed.')\n", - " \n", + "\n", "# Create and show the figure\n", "plt.figure(\"Vapor Fraction\")\n", "plt.plot(Q, V)\n", @@ -676,18 +1171,21 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { - "cell_type": "code", - "execution_count": 30, "metadata": { - "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-06T17:04:48.800601Z", + "start_time": "2025-06-06T17:04:46.438264Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# import the solve_successful checking function from workshop tools\n", "from idaes_examples.mod.tut.workshoptools import solve_successful\n", @@ -700,7 +1198,7 @@ "V = []\n", "\n", "# re-initialize model\n", - "m.fs.flash.initialize(outlvl=idaeslog.WARNING)\n", + "FlashInitializer.initialize(m.fs.flash)\n", "\n", "# Todo: Write the for loop specification using numpy's linspace\n", "for duty in np.linspace(-17000, 25000, 50):\n", @@ -731,11 +1229,244 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_in: Initialization Step 5 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 1 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 2 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 3 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 4 optimal - .\n", + "2025-06-06 11:04:46 [INFO] idaes.init.fs.flash.control_volume.properties_out: Initialization Step 5 optimal - .\n", + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 43 }, { + "metadata": { + "tags": [ + "exercise" + ] + }, "cell_type": "markdown", - "metadata": {}, "source": [ "
\n", "Inline Exercise:\n", @@ -744,27 +1475,27 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" ] }, + "cell_type": "code", + "source": "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor", "outputs": [], - "source": [ - "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor" - ] + "execution_count": null }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:02.101331Z", + "start_time": "2025-06-06T17:05:00.157447Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# Todo: generate a figure of heat duty vs. mole fraction of Benzene in the vapor\n", "Q = []\n", @@ -797,18 +1528,247 @@ "plt.xlabel(\"Heat Duty [J]\")\n", "plt.ylabel(\"Vapor Benzene Mole Fraction [-]\")\n", "plt.show()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulating with Q = -17000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -16142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -15285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -14428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -13571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -12714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -11000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -10142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -9285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -8428.57142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -7571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -6714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5857.142857142857\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -5000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -4142.857142857143\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -3285.7142857142862\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -2428.5714285714294\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -1571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = -714.2857142857156\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 142.8571428571413\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 1857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 2714.2857142857138\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 3571.4285714285725\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 4428.5714285714275\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 5285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 6142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 7857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 8714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 9571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 10428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 11285.714285714286\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 12142.857142857141\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 13857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 14714.285714285714\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 15571.428571428569\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 16428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 17285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 18142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 19857.142857142855\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 20714.28571428571\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 21571.428571428572\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 22428.571428571428\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 23285.714285714283\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 24142.857142857145\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n", + "Simulating with Q = 25000.0\n", + "WARNING: model contains export suffix 'scaling_factor' that contains 7\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "... solve successful.\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 44 }, { - "cell_type": "markdown", "metadata": {}, + "cell_type": "markdown", "source": [ "Recall that the IDAES framework is an equation-oriented modeling environment. This means that we can specify \"design\" problems natively. That is, there is no need to have our specifications on the inlet alone. We can put specifications on the outlet as long as we retain a well-posed, square system of equations.\n", "\n", "For example, we can remove the specification on heat duty and instead specify that we want the mole fraction of Benzene in the vapor outlet to be equal to 0.6. The mole fraction is not a native variable in the property block, so we cannot use \"fix\". We can, however, add a constraint to the model.\n", "\n", "Note that we have been executing a number of solves on the problem, and may not be sure of the current state. To help convergence, therefore, we will first call initialize, then add the new constraint and solve the problem. Note that the reference for the mole fraction of Benzene in the vapor outlet is `m.fs.flash.vap_outlet.mole_frac_comp[0, \"benzene\"]`.\n", - "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", "Fill in the missing code below and add a constraint on the mole fraction of Benzene (to a value of 0.6) to find the required heat duty.\n", @@ -816,14 +1776,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.363302Z", + "start_time": "2025-06-06T17:05:04.960601Z" + }, "tags": [ "exercise" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -839,17 +1801,118 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 136\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 41\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.07e-08 1.01e-04 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.46e+00 2.42e-01 -1.0 4.86e+02 - 9.90e-01 1.00e+00f 1\n", + " 2 0.0000000e+00 5.55e+01 5.60e-03 -1.0 3.00e+03 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 1.91e+00 4.24e-05 -1.0 5.68e+02 - 1.00e+00 1.00e+00h 1\n", + " 4 0.0000000e+00 1.53e-05 1.90e-06 -2.5 1.35e+00 - 1.00e+00 1.00e+00h 1\n", + " 5 0.0000000e+00 4.66e-10 1.50e-09 -3.8 8.72e-03 - 1.00e+00 1.00e+00h 1\n", + " 6 0.0000000e+00 2.18e-11 1.84e-11 -5.7 1.92e-03 - 1.00e+00 1.00e+00h 1\n", + " 7 0.0000000e+00 1.46e-11 2.51e-14 -8.6 2.10e-04 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 7\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 2.5059035640133008e-14 2.5059035640133008e-14\n", + "Constraint violation....: 4.8801876740451558e-13 1.4551915228366852e-11\n", + "Complementarity.........: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "Overall NLP error.......: 2.5059101787473095e-09 2.5059101787473095e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 9\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 9\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 8\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 7\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.002\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 4059.3 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.51773 0.48227 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60690 0.38524 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.39310 0.61476 \n", + " temperature kelvin 368.00 368.85 368.85 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 45 }, { - "cell_type": "code", - "execution_count": null, "metadata": { + "ExecuteTime": { + "end_time": "2025-06-06T17:05:05.768445Z", + "start_time": "2025-06-06T17:05:05.378930Z" + }, "tags": [ "solution" ] }, - "outputs": [], + "cell_type": "code", "source": [ "# re-initialize the model - this may or may not be required depending on current state but safe to initialize\n", "m.fs.flash.heat_duty.fix(0)\n", @@ -868,7 +1931,102 @@ "\n", "# Check stream condition\n", "m.fs.flash.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 6\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: \n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 137\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 72\n", + "\n", + "Total number of variables............................: 42\n", + " variables with only lower bounds: 3\n", + " variables with lower and upper bounds: 10\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 42\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.40e-02 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.64e+02 7.01e-02 -1.0 5.15e+03 - 9.87e-01 1.00e+00h 1\n", + " 2 0.0000000e+00 9.59e-02 2.03e-03 -1.0 7.07e+01 - 9.90e-01 1.00e+00h 1\n", + " 3 0.0000000e+00 6.96e-08 2.50e-06 -1.0 4.13e-01 - 9.98e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 3\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 8.9151738215745240e-11 6.9550878833979368e-08\n", + "\n", + "\n", + "Number of objective function evaluations = 4\n", + "Number of objective gradient evaluations = 4\n", + "Number of equality constraint evaluations = 4\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 4\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 3\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.001\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "====================================================================================\n", + "Unit : fs.flash Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 5083.6 : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol mole / second 1.0000 0.54833 0.45167 \n", + " mole_frac_comp benzene dimensionless 0.50000 0.60000 0.37860 \n", + " mole_frac_comp toluene dimensionless 0.50000 0.40000 0.62140 \n", + " temperature kelvin 368.00 369.07 369.07 \n", + " pressure pascal 1.0132e+05 1.0132e+05 1.0132e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 46 } ], "metadata": { @@ -893,4 +2051,4 @@ }, "nbformat": 4, "nbformat_minor": 3 -} +} \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 4f11e1c6..2fca2a80 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "header", "hide-cell" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } }, - "outputs": [], "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", @@ -23,7 +25,9 @@ "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", "# for full copyright and license information.\n", "###############################################################################" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "markdown", @@ -32,20 +36,34 @@ "\n", "# HDA Flowsheet Simulation and Optimization\n", "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", "\n", "## Learning outcomes\n", "\n", "\n", "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", + "- Connecting unit models in a flowsheet using Arcs\n", "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", "- Formulate and solve an optimization problem\n", " - Defining an objective function\n", " - Setting variable bounds\n", - " - Adding additional constraints \n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", "\n", "\n", "## Problem Statement\n", @@ -81,7 +99,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Importing required pyomo and idaes components\n", + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", "\n", "\n", "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", @@ -100,9 +119,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, "source": [ "from pyomo.environ import (\n", " Constraint,\n", @@ -115,44 +137,60 @@ " value,\n", ")\n", "from pyomo.network import Arc, SequentialDecomposition" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", "- Mixer\n", "- Heater\n", "- StoichiometricReactor\n", "- **Flash**\n", "- Separator (splitter) \n", - "- PressureChanger" + "- PressureChanger\n", + "- Product" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, "source": [ "from idaes.core import FlowsheetBlock" - ] + ], + "outputs": [], + "execution_count": 3 }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", ")" - ] + ], + "outputs": [], + "execution_count": 4 }, { "cell_type": "markdown", @@ -166,30 +204,38 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } }, - "outputs": [], "source": [ "# Todo: import flash model from idaes.models.unit_models" - ] + ], + "outputs": [], + "execution_count": 5 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } }, - "outputs": [], "source": [ "# Todo: import flash model from idaes.models.unit_models\n", "from idaes.models.unit_models import Flash" - ] + ], + "outputs": [], + "execution_count": 6 }, { "cell_type": "markdown", @@ -200,24 +246,31 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, "source": [ "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", "from idaes.core.solvers import get_solver\n", "from idaes.core.util.exceptions import InitializationError" - ] + ], + "outputs": [], + "execution_count": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Importing required thermo and reaction package\n", + "### 1.2 Importing required thermo and reaction package\n", "\n", "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", "\n", @@ -233,32 +286,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, "source": [ "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] + ], + "outputs": [], + "execution_count": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Constructing the Flowsheet\n", + "## 2 Constructing the Flowsheet\n", "\n", "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, "source": [ "m = ConcreteModel()\n", "m.fs = FlowsheetBlock(dynamic=False)" - ] + ], + "outputs": [], + "execution_count": 9 }, { "cell_type": "markdown", @@ -269,34 +332,48 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, "source": [ "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", " property_package=m.fs.thermo_params\n", ")" - ] + ], + "outputs": [], + "execution_count": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Adding Unit Models\n", + "### 2.1 Adding Unit Models\n", "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", + " num_inlets=3,\n", ")\n", "\n", "m.fs.H101 = Heater(\n", @@ -304,11 +381,17 @@ " has_pressure_change=False,\n", " has_phase_equilibrium=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 11 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
\n", "Inline Exercise:\n", @@ -325,26 +408,32 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } }, - "outputs": [], "source": [ "# Todo: Add reactor with the specifications above" - ] + ], + "outputs": [], + "execution_count": 12 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } }, - "outputs": [], "source": [ "# Todo: Add reactor with the specifications above\n", "m.fs.R101 = StoichiometricReactor(\n", @@ -354,7 +443,9 @@ " has_heat_transfer=True,\n", " has_pressure_change=False,\n", ")" - ] + ], + "outputs": [], + "execution_count": 13 }, { "cell_type": "markdown", @@ -370,29 +461,35 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", " has_heat_transfer=True,\n", " has_pressure_change=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 14 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -412,25 +509,60 @@ " has_heat_transfer=True,\n", " has_pressure_change=True,\n", ")" - ] + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Connecting Unit Models using Arcs\n", + "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] + ], + "outputs": [], + "execution_count": 17 }, { "cell_type": "markdown", @@ -439,39 +571,57 @@ "\n", "![](HDA_flowsheet.png) \n", "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ "
\n", "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" ] }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } }, - "outputs": [], "source": [ "# Todo: Connect the H101 outlet to R101 inlet" - ] + ], + "outputs": [], + "execution_count": 18 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } }, - "outputs": [], "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] + ], + "outputs": [], + "execution_count": 19 }, { "cell_type": "markdown", @@ -482,16 +632,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 }, { "cell_type": "markdown", @@ -502,18 +678,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] + ], + "outputs": [], + "execution_count": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Adding expressions to compute purity and operating costs\n", + "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", "\n", @@ -529,9 +710,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, "source": [ "m.fs.purity = Expression(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -540,7 +724,9 @@ " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", " )\n", ")" - ] + ], + "outputs": [], + "execution_count": 23 }, { "cell_type": "markdown", @@ -551,14 +737,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" - ] + ], + "outputs": [], + "execution_count": 24 }, { "cell_type": "markdown", @@ -575,14 +766,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" - ] + ], + "outputs": [], + "execution_count": 25 }, { "cell_type": "markdown", @@ -593,78 +789,143 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." ] }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Fixing feed conditions\n", + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", "\n", "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, "source": [ "print(degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.996567Z", + "start_time": "2025-06-11T22:13:28.973555Z" + } }, - "outputs": [], "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" - ] + ], + "outputs": [], + "execution_count": 29 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", "
    \n", "
  • FH2 = 0.30 mol/s
  • \n", "
  • FCH4 = 0.02 mol/s
  • \n", @@ -677,39 +938,49 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Fixing unit model specifications\n", + "### 4.2 Fixing unit model specifications\n", "\n", "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.fix(600)" - ] + ], + "outputs": [], + "execution_count": 32 }, { "cell_type": "markdown", @@ -720,9 +991,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", @@ -736,7 +1010,9 @@ "\n", "m.fs.R101.conversion.fix(0.75)\n", "m.fs.R101.heat_duty.fix(0)" - ] + ], + "outputs": [], + "execution_count": 33 }, { "cell_type": "markdown", @@ -747,17 +1023,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" - ] + ], + "outputs": [], + "execution_count": 34 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -773,30 +1058,38 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } }, - "outputs": [], "source": [ "# Todo: Set conditions for Flash F102" - ] + ], + "outputs": [], + "execution_count": 35 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } }, - "outputs": [], "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" - ] + ], + "outputs": [], + "execution_count": 36 }, { "cell_type": "markdown", @@ -807,17 +1100,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" - ] + ], + "outputs": [], + "execution_count": 37 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -829,68 +1131,114 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } }, - "outputs": [], "source": [ "# Todo: print the degrees of freedom" - ] + ], + "outputs": [], + "execution_count": 38 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } }, - "outputs": [], "source": [ "print(degrees_of_freedom(m))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.304978Z", + "start_time": "2025-06-11T22:13:29.282394Z" + } }, - "outputs": [], "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" - ] + ], + "outputs": [], + "execution_count": 40 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Initialization\n", + "## 5 Initializing the Model\n", + "\n", "\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", "\n", - "![](HDA_flowsheet.png) \n" + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -901,7 +1249,9 @@ "G = seq.create_graph(m)\n", "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", "order = seq.calculation_order(G)" - ] + ], + "outputs": [], + "execution_count": 41 }, { "cell_type": "markdown", @@ -912,13 +1262,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 }, { "cell_type": "markdown", @@ -929,15 +1292,32 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { - "scrolled": true + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } }, - "outputs": [], "source": [ "for o in order:\n", " print(o[0].name)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 }, { "cell_type": "markdown", @@ -948,25 +1328,28 @@ "![](HDA_tear_stream.png) \n", "\n", "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Liq\", \"benzene\"): 1e-5,\n", " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -974,7 +1357,9 @@ "\n", "# Pass the tear_guess to the SD tool\n", "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] + ], + "outputs": [], + "execution_count": 44 }, { "cell_type": "markdown", @@ -985,9 +1370,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, "source": [ "def function(unit):\n", " try:\n", @@ -996,7 +1384,9 @@ " except InitializationError:\n", " solver = get_solver()\n", " solver.solve(unit)" - ] + ], + "outputs": [], + "execution_count": 45 }, { "cell_type": "markdown", @@ -1007,165 +1397,1060 @@ }, { "cell_type": "code", - "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "seq.run(m, function)" + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" ] }, { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", "source": [ "
    \n", "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
    \n", "results = solver.solve(m, tee=True)\n", "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
    \n" ] }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } }, - "outputs": [], "source": [ "# Create the solver object\n", "\n", - "\n", "# Solve the model" - ] + ], + "outputs": [], + "execution_count": 55 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } }, - "outputs": [], "source": [ "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", + "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.344624Z", + "start_time": "2025-06-11T22:13:32.341522Z" + } }, - "outputs": [], "source": [ "# Check solver solve status\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert results.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 57 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Analyze the results of the square problem\n", - "\n", + "## 7 Analyze the results\n", "\n", - "What is the total operating cost? " + "\n" ] }, { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, "cell_type": "code", - "execution_count": null, + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.166006Z", + "start_time": "2025-06-11T22:13:34.094011Z" + } }, - "outputs": [], "source": [ "import pytest\n", "\n", "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 61 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.213201Z", + "start_time": "2025-06-11T22:13:34.210228Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "\n", "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 63 }, { "cell_type": "markdown", "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -1174,25 +2459,33 @@ "\n", "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", + "## 8 Optimization\n", "\n", "\n", "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", @@ -1219,12 +2512,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] + ], + "outputs": [], + "execution_count": 65 }, { "cell_type": "markdown", @@ -1235,19 +2533,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", "m.fs.F101.vap_outlet.temperature.unfix()\n", "m.fs.F102.vap_outlet.temperature.unfix()" - ] + ], + "outputs": [], + "execution_count": 66 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1260,43 +2567,55 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } }, - "outputs": [], "source": [ "# Todo: Unfix deltaP for F102" - ] + ], + "outputs": [], + "execution_count": 67 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } }, - "outputs": [], "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" - ] + ], + "outputs": [], + "execution_count": 68 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.535666Z", + "start_time": "2025-06-11T22:13:34.502099Z" + } }, - "outputs": [], "source": [ "assert degrees_of_freedom(m) == 5" - ] + ], + "outputs": [], + "execution_count": 69 }, { "cell_type": "markdown", @@ -1315,17 +2634,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" - ] + ], + "outputs": [], + "execution_count": 70 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1337,31 +2665,39 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } }, - "outputs": [], "source": [ "# Todo: Set the bounds for reactor outlet temperature" - ] + ], + "outputs": [], + "execution_count": 71 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } }, - "outputs": [], "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", "m.fs.R101.outlet.temperature[0].setlb(600)\n", "m.fs.R101.outlet.temperature[0].setub(800)" - ] + ], + "outputs": [], + "execution_count": 72 }, { "cell_type": "markdown", @@ -1372,9 +2708,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -1382,7 +2721,9 @@ "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] + ], + "outputs": [], + "execution_count": 73 }, { "cell_type": "markdown", @@ -1393,19 +2734,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, "source": [ "m.fs.overhead_loss = Constraint(\n", " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", ")" - ] + ], + "outputs": [], + "execution_count": 74 }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [ + "exercise" + ] + }, "source": [ "
    \n", "Inline Exercise:\n", @@ -1417,32 +2767,40 @@ }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } }, - "outputs": [], "source": [ "# Todo: Add minimum product flow constraint" - ] + ], + "outputs": [], + "execution_count": 75 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } }, - "outputs": [], "source": [ "# Todo: Add minimum product flow constraint\n", "m.fs.product_flow = Constraint(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", ")" - ] + ], + "outputs": [], + "execution_count": 76 }, { "cell_type": "markdown", @@ -1453,12 +2811,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] + ], + "outputs": [], + "execution_count": 77 }, { "cell_type": "markdown", @@ -1472,43 +2835,186 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, "source": [ "results = solver.solve(m, tee=True)" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.223076Z", + "start_time": "2025-06-11T22:13:35.219792Z" + } }, - "outputs": [], "source": [ "# Check for solver solve status\n", "from pyomo.environ import TerminationCondition\n", "\n", "assert results.solver.termination_condition == TerminationCondition.optimal" - ] + ], + "outputs": [], + "execution_count": 79 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Optimization Results\n", + "### 8.1 Optimization Results\n", "\n", "Display the results and product specifications" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -1523,21 +3029,93 @@ "print()\n", "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" - ] + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.348144Z", + "start_time": "2025-06-11T22:13:35.343061Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ] + ], + "outputs": [], + "execution_count": 81 }, { "cell_type": "markdown", @@ -1548,49 +3126,66 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 }, { "cell_type": "code", - "execution_count": null, "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.448075Z", + "start_time": "2025-06-11T22:13:35.443091Z" + } }, - "outputs": [], "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, + ], "outputs": [], - "source": [] + "execution_count": 83 } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 86569f0e..329c0c99 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1,1363 +1,2698 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"reaction_package\": m.fs.reaction_params
    • \n", - "
    • \"has_heat_of_reaction\": True
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
    \n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
      \n", - "
    • 2.2E-4 dollars/kW for H101
    • \n", - "
    • 1.9E-4 dollars/kW for F102
    • \n", - "
    \n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
      \n", - "
    • FH2 = 0.30 mol/s
    • \n", - "
    • FCH4 = 0.02 mol/s
    • \n", - "
    • Remaining components = 1e-5 mol/s
    • \n", - "
    • T = 303.2 K
    • \n", - "
    • P = 350000 Pa
    • \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
      \n", - "
    • T = 375 K
    • \n", - "
    • deltaP = -200000
    • \n", - "
    \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
    \n", + "Maintainer: Tanner Polley
    \n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
      \n", + "
    • hda_ideal_VLE as thermo_props
    • \n", + "
    • hda_reaction as reaction_props
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
      \n", + "
    • 2.2E-4 dollars/kW for H101
    • \n", + "
    • 1.9E-4 dollars/kW for F102
    • \n", + "
    \n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
      \n", + "
    • FH2 = 0.30 mol/s
    • \n", + "
    • FCH4 = 0.02 mol/s
    • \n", + "
    • Remaining components = 1e-5 mol/s
    • \n", + "
    • T = 303.2 K
    • \n", + "
    • P = 350000 Pa
    • \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index ef8abc44..91c14462 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1,1344 +1,2698 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"reaction_package\": m.fs.reaction_params
    • \n", - "
    • \"has_heat_of_reaction\": True
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
      \n", - "
    • \"property_package\": m.fs.thermo_params
    • \n", - "
    • \"has_heat_transfer\": True
    • \n", - "
    • \"has_pressure_change\": False
    • \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
    \n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
      \n", - "
    • 2.2E-4 dollars/kW for H101
    • \n", - "
    • 1.9E-4 dollars/kW for F102
    • \n", - "
    \n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
      \n", - "
    • FH2 = 0.30 mol/s
    • \n", - "
    • FCH4 = 0.02 mol/s
    • \n", - "
    • Remaining components = 1e-5 mol/s
    • \n", - "
    • T = 303.2 K
    • \n", - "
    • P = 350000 Pa
    • \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
      \n", - "
    • T = 375 K
    • \n", - "
    • deltaP = -200000
    • \n", - "
    \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
    \n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    \n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
    " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
    \n", + "Maintainer: Tanner Polley
    \n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
      \n", + "
    • hda_ideal_VLE as thermo_props
    • \n", + "
    • hda_reaction as reaction_props
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"reaction_package\": m.fs.reaction_params
    • \n", + "
    • \"has_heat_of_reaction\": True
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
      \n", + "
    • \"property_package\": m.fs.thermo_params
    • \n", + "
    • \"has_heat_transfer\": True
    • \n", + "
    • \"has_pressure_change\": False
    • \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
      \n", + "
    • 2.2E-4 dollars/kW for H101
    • \n", + "
    • 1.9E-4 dollars/kW for F102
    • \n", + "
    \n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
      \n", + "
    • FH2 = 0.30 mol/s
    • \n", + "
    • FCH4 = 0.02 mol/s
    • \n", + "
    • Remaining components = 1e-5 mol/s
    • \n", + "
    • T = 303.2 K
    • \n", + "
    • P = 350000 Pa
    • \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
      \n", + "
    • T = 375 K
    • \n", + "
    • deltaP = -200000
    • \n", + "
    \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
    \n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
    \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    \n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
    \n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
    " + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 088af81e..7e8b3ff6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1,1483 +1,3043 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
    \n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
    \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
      \n", - "
    • hda_ideal_VLE as thermo_props
    • \n", - "
    • hda_reaction as reaction_props
    • \n", - "
    \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 83d872c4..14dbf8bc 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1,1498 +1,2868 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 29" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "import pytest\n", - "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert degrees_of_freedom(m) == 5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "# Check for solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", - "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "testing" - ] - }, - "outputs": [], - "source": [ - "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.996567Z", + "start_time": "2025-06-11T22:13:28.973555Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 29" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.304978Z", + "start_time": "2025-06-11T22:13:29.282394Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 0" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.344624Z", + "start_time": "2025-06-11T22:13:32.341522Z" + } + }, + "source": [ + "# Check solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.166006Z", + "start_time": "2025-06-11T22:13:34.094011Z" + } + }, + "source": [ + "import pytest\n", + "\n", + "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" + ], + "outputs": [], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.213201Z", + "start_time": "2025-06-11T22:13:34.210228Z" + } + }, + "source": [ + "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" + ], + "outputs": [], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.535666Z", + "start_time": "2025-06-11T22:13:34.502099Z" + } + }, + "source": [ + "assert degrees_of_freedom(m) == 5" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.223076Z", + "start_time": "2025-06-11T22:13:35.219792Z" + } + }, + "source": [ + "# Check for solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.348144Z", + "start_time": "2025-06-11T22:13:35.343061Z" + } + }, + "source": [ + "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", + "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" + ], + "outputs": [], + "execution_count": 81 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.448075Z", + "start_time": "2025-06-11T22:13:35.443091Z" + } + }, + "source": [ + "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" + ], + "outputs": [], + "execution_count": 83 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 088af81e..7e8b3ff6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1,1483 +1,3043 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "header", - "hide-cell" - ] - }, - "outputs": [], - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse \n", - "Maintainer: Brandon Paul \n", - "Updated: 2023-06-01 \n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints \n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 → C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required pyomo and idaes components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core import FlowsheetBlock" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " Mixer,\n", - " Separator as Splitter,\n", - " Heater,\n", - " StoichiometricReactor,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Mixer (assigned a name M101) and a Heater (assigned a name H101). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the Mixer unit model here is given a `list` consisting of names to the three inlets. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " inlet_list=[\"toluene_feed\", \"hydrogen_feed\", \"vapor_recycle\"],\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101), PressureChanger(C101) and the second Flash(F102). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the mixer(M101) to the inlet of the heater(H101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.vapor_recycle)\n", - "m.fs.s10 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.toluene_feed.temperature.fix(303.2)\n", - "m.fs.M101.toluene_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.M101.hydrogen_feed.temperature.fix(303.2)\n", - "m.fs.M101.hydrogen_feed.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set conditions for Flash F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: print the degrees of freedom" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "print(degrees_of_freedom(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialization\n", - "\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet.\n", - "\n", - "![](HDA_flowsheet.png) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "for o in order:\n", - " print(o[0].name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "seq.run(m, function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now initialized the flowsheet. Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - " \n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "\n", - "\n", - "# Solve the model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Create the solver object\n", - "from idaes.core.solvers import get_solver\n", - "\n", - "solver = get_solver()\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyze the results of the square problem\n", - "\n", - "\n", - "What is the total operating cost? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101.\n", - "\n", - "
\n", - "Inline Exercise:\n", - "How much benzene are we losing in the F101 vapor outlet stream?\n", - "
\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "You can query additional variables here if you like. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "exercise" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "solution" - ] - }, - "outputs": [], - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results = solver.solve(m, tee=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Optimal Values\")\n", - "print()\n", - "\n", - "print(\"H101 outlet temperature = \", value(m.fs.H101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"R101 outlet temperature = \", value(m.fs.R101.outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F101 outlet temperature = \", value(m.fs.F101.vap_outlet.temperature[0]), \"K\")\n", - "\n", - "print()\n", - "print(\"F102 outlet temperature = \", value(m.fs.F102.vap_outlet.temperature[0]), \"K\")\n", - "print(\"F102 outlet pressure = \", value(m.fs.F102.vap_outlet.pressure[0]), \"Pa\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:25.418463Z", + "start_time": "2025-06-11T22:13:25.412645Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-06-03\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "- 1 Importing Modules\n", + "- 2 Building a Model\n", + "- 3 Scaling the Model\n", + "- 4 Specifying the Model\n", + "- 5 Initializing the Model\n", + "- 6 Solving the Model\n", + "- 7 Analyzing and Visualizing the Results\n", + "- 8 Optimizing the Model\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required pyomo and idaes components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:26.066510Z", + "start_time": "2025-06-11T22:13:25.662098Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " SolverFactory,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.637361Z", + "start_time": "2025-06-11T22:13:26.082580Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.752223Z", + "start_time": "2025-06-11T22:13:27.645348Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger, IsentropicPressureChangerInitializer,\n", + " Mixer, MixerInitializer,\n", + " Separator as Splitter, SeparatorInitializer,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.763417Z", + "start_time": "2025-06-11T22:13:27.761004Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.774708Z", + "start_time": "2025-06-11T22:13:27.772299Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.788004Z", + "start_time": "2025-06-11T22:13:27.784891Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "from idaes.core.scaling.util import set_scaling_factor\n", + "from idaes.core.scaling.autoscaling import AutoScaler\n", + "\n", + "# Import idaes logger to set output levels\n", + "import idaes.logger as idaeslog\n", + "from idaes.core.solvers import get_solver\n", + "from idaes.core.util.exceptions import InitializationError" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.806315Z", + "start_time": "2025-06-11T22:13:27.798068Z" + } + }, + "source": [ + "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", + "from idaes_examples.mod.hda import hda_reaction as reaction_props" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.819615Z", + "start_time": "2025-06-11T22:13:27.814729Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.841949Z", + "start_time": "2025-06-11T22:13:27.829949Z" + } + }, + "source": [ + "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + " property_package=m.fs.thermo_params\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.876870Z", + "start_time": "2025-06-11T22:13:27.853517Z" + } + }, + "source": [ + "m.fs.I101 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.894702Z", + "start_time": "2025-06-11T22:13:27.891599Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.921265Z", + "start_time": "2025-06-11T22:13:27.910910Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.947463Z", + "start_time": "2025-06-11T22:13:27.933993Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:27.987933Z", + "start_time": "2025-06-11T22:13:27.964931Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.009893Z", + "start_time": "2025-06-11T22:13:28.001769Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.P101 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(\n", + " property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(\n", + " property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.034324Z", + "start_time": "2025-06-11T22:13:28.031285Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "![](HDA_flowsheet.png) \n", + "\n", + "\n" + ] + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.055815Z", + "start_time": "2025-06-11T22:13:28.052507Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.084663Z", + "start_time": "2025-06-11T22:13:28.082008Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.118422Z", + "start_time": "2025-06-11T22:13:28.113732Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + ], + "outputs": [], + "execution_count": 20 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.148879Z", + "start_time": "2025-06-11T22:13:28.144601Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.198384Z", + "start_time": "2025-06-11T22:13:28.176239Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.222088Z", + "start_time": "2025-06-11T22:13:28.218400Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " / (\n", + " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.248216Z", + "start_time": "2025-06-11T22:13:28.244244Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.271256Z", + "start_time": "2025-06-11T22:13:28.268284Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.295580Z", + "start_time": "2025-06-11T22:13:28.292627Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## 3 Scaling the Model\n", + "\n", + "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", + "\n", + "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", + "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", + "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", + "\n", + "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.915668Z", + "start_time": "2025-06-11T22:13:28.317020Z" + } + }, + "cell_type": "code", + "source": [ + "autoscaler = AutoScaler()\n", + "autoscaler.scale_model(m)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", + "component keys that are not exported as part of the NL file. Skipping.\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:28.948173Z", + "start_time": "2025-06-11T22:13:28.924210Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.012096Z", + "start_time": "2025-06-11T22:13:29.006965Z" + } + }, + "source": [ + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.036253Z", + "start_time": "2025-06-11T22:13:29.031731Z" + } + }, + "source": [ + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", + "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.078559Z", + "start_time": "2025-06-11T22:13:29.075531Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.111099Z", + "start_time": "2025-06-11T22:13:29.106956Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " == (\n", + " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.128972Z", + "start_time": "2025-06-11T22:13:29.125273Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.149002Z", + "start_time": "2025-06-11T22:13:29.146476Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.171742Z", + "start_time": "2025-06-11T22:13:29.168352Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.196247Z", + "start_time": "2025-06-11T22:13:29.192956Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.220402Z", + "start_time": "2025-06-11T22:13:29.217907Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.263397Z", + "start_time": "2025-06-11T22:13:29.241129Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 39 + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.316042Z", + "start_time": "2025-06-11T22:13:29.313537Z" + } + }, + "cell_type": "code", + "source": "", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.330212Z", + "start_time": "2025-06-11T22:13:29.324872Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.353734Z", + "start_time": "2025-06-11T22:13:29.350730Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.391173Z", + "start_time": "2025-06-11T22:13:29.388153Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.430684Z", + "start_time": "2025-06-11T22:13:29.426921Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.465203Z", + "start_time": "2025-06-11T22:13:29.462031Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.505027Z", + "start_time": "2025-06-11T22:13:29.501933Z" + } + }, + "source": "# seq.run(m, function)", + "outputs": [], + "execution_count": 46 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "### 5.2 Manual Propogation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.536579Z", + "start_time": "2025-06-11T22:13:29.533074Z" + } + }, + "cell_type": "code", + "source": "from idaes.core.util.initialization import propagate_state", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.583098Z", + "start_time": "2025-06-11T22:13:29.553382Z" + } + }, + "cell_type": "code", + "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 initially\n" + ] + } + ], + "execution_count": 48 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.633917Z", + "start_time": "2025-06-11T22:13:29.610932Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.s03_expanded.deactivate()\n", + "\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 10 after deactivating the tear stream\n" + ] + } + ], + "execution_count": 49 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:29.702707Z", + "start_time": "2025-06-11T22:13:29.654459Z" + } + }, + "cell_type": "code", + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5,\n", + " (0, \"Liq\", \"toluene\"): 0.30,\n", + " (0, \"Liq\", \"methane\"): 1e-5,\n", + " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", + " (0, \"Vap\", \"benzene\"): 1e-5,\n", + " (0, \"Vap\", \"toluene\"): 1e-5,\n", + " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + "\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + "DOF_initial = degrees_of_freedom(m)\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after providing the initial guesses\n" + ] + } + ], + "execution_count": 50 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.347435Z", + "start_time": "2025-06-11T22:13:29.712721Z" + } + }, + "cell_type": "code", + "source": [ + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + ] + } + ], + "execution_count": 51 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.935414Z", + "start_time": "2025-06-11T22:13:31.357025Z" + } + }, + "cell_type": "code", + "source": [ + "solver = get_solver()\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", + "tol=1e-06\n", + "max_iter=200\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1112\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 999\n", + "\n", + "Total number of variables............................: 380\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 186\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 380\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", + " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", + " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", + " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", + " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", + " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", + " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", + " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", + " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", + " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", + " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", + " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", + " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", + " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", + " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", + " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", + " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", + " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", + " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", + " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", + " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", + " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", + " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", + " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", + " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", + " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", + " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", + " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", + " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", + " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", + " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", + " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", + " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", + " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", + " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", + " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", + " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", + " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", + " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", + " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", + " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", + " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", + " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", + " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", + " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", + " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", + " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", + " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", + " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", + " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", + " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", + " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", + " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", + " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", + " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", + " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", + " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", + " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", + " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", + " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", + " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", + " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", + " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", + " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", + " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", + " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", + " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", + " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", + " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", + " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", + " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", + " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", + " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", + " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", + " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", + " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", + " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", + " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", + " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", + " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", + " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", + " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", + " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", + " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", + " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", + " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", + " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", + " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", + " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", + " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", + " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", + " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", + " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", + " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", + " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", + " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", + " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", + " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", + " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", + " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", + " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", + " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", + " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", + " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", + " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", + " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", + " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", + " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", + " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", + " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", + " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", + " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", + " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", + " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", + " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", + " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", + " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", + " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", + " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", + " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", + " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", + " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", + " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", + " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", + " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", + " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", + " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", + " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", + " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", + " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", + " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", + " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", + " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", + " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", + " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", + " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", + " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", + " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", + " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", + " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", + " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", + " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", + " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", + " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", + " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", + " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", + " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", + " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", + " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", + " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", + " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", + " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", + " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", + " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", + " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", + " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", + " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", + " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", + " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", + " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", + " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", + " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", + " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", + " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", + " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", + " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", + " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", + " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", + " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", + " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", + " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", + " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", + " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", + " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", + " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", + " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", + " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + "\n", + "Number of Iterations....: 200\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", + "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", + "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "\n", + "\n", + "Number of objective function evaluations = 1605\n", + "Number of objective gradient evaluations = 175\n", + "Number of equality constraint evaluations = 1605\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 202\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 200\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", + "Total CPU secs in NLP function evaluations = 0.025\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"unknown\";\n", + " - termination condition: maxIterations\n", + " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", + " Exceeded.\n" + ] + } + ], + "execution_count": 52 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.967629Z", + "start_time": "2025-06-11T22:13:31.943574Z" + } + }, + "cell_type": "code", + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 53 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6 Solving the Model" + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:31.982093Z", + "start_time": "2025-06-11T22:13:31.978929Z" + } + }, + "cell_type": "code", + "source": [ + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 500,\n", + " 'tol': 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 54 + }, + { + "metadata": { + "tags": [ + "exercise" + ] + }, + "cell_type": "markdown", + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.012062Z", + "start_time": "2025-06-11T22:13:32.008341Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:32.320588Z", + "start_time": "2025-06-11T22:13:32.041379Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(solver_options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)\n" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1163\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 1062\n", + "\n", + "Total number of variables............................: 390\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 196\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", + " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", + " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", + " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", + " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", + " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", + " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", + " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", + " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", + " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", + " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", + " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", + " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", + " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", + " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", + " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", + " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", + " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", + " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", + " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", + " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", + " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", + " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", + " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", + " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", + " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", + " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", + " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", + " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", + " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", + " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", + " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", + " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", + " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", + " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", + " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", + " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", + " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", + " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", + " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", + " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", + " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", + " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", + " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", + " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", + " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", + " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", + " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", + " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", + " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", + " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", + " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", + " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", + " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", + " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", + " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", + " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", + " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", + " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", + " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", + " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", + " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", + " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", + " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 81\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 162\n", + "Number of objective gradient evaluations = 23\n", + "Number of equality constraint evaluations = 162\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 83\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 81\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + }, + { + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.874186Z", + "start_time": "2025-06-11T22:13:32.362868Z" + } + }, + "cell_type": "code", + "source": "m.fs.visualize('HDA-Flowsheet')", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", + "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" + ] + }, + { + "data": { + "text/plain": [ + "VisualizeResult(store=, port=49167, server=, save_diagram=>)" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 58 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:33.985892Z", + "start_time": "2025-06-11T22:13:33.889113Z" + } + }, + "cell_type": "code", + "source": "m.fs.report()", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", + " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "What is the total operating cost?" + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.015352Z", + "start_time": "2025-06-11T22:13:34.012518Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 419122.33874473866\n" + ] + } + ], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.197557Z", + "start_time": "2025-06-11T22:13:34.174732Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7352.5 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", + " temperature kelvin 325.00 375.00 375.00 \n", + " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242962943922332\n" + ] + } + ], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.253529Z", + "start_time": "2025-06-11T22:13:34.238100Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", + "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", + "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", + "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", + "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", + "temperature kelvin 771.85 325.00 \n", + "pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.276719Z", + "start_time": "2025-06-11T22:13:34.271416Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.337438Z", + "start_time": "2025-06-11T22:13:34.332415Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.399247Z", + "start_time": "2025-06-11T22:13:34.395221Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.463653Z", + "start_time": "2025-06-11T22:13:34.459960Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.589902Z", + "start_time": "2025-06-11T22:13:34.585528Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.678092Z", + "start_time": "2025-06-11T22:13:34.673513Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.713177Z", + "start_time": "2025-06-11T22:13:34.709843Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.763569Z", + "start_time": "2025-06-11T22:13:34.759916Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.806470Z", + "start_time": "2025-06-11T22:13:34.801455Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.837136Z", + "start_time": "2025-06-11T22:13:34.832491Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.887385Z", + "start_time": "2025-06-11T22:13:34.882862Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:34.917217Z", + "start_time": "2025-06-11T22:13:34.912683Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.209235Z", + "start_time": "2025-06-11T22:13:34.962108Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", + "component keys that are not exported as part of the NL file. Skipping.\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=500\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma27.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1191\n", + "Number of nonzeros in inequality constraint Jacobian.: 5\n", + "Number of nonzeros in Lagrangian Hessian.............: 1065\n", + "\n", + "Total number of variables............................: 395\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 199\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 390\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", + " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", + " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", + " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", + " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", + " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", + " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", + " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", + " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", + " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", + " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", + " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", + " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", + " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", + " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", + " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", + " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", + " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", + " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", + " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", + " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", + " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", + " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", + " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", + " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", + " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", + " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", + " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", + " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", + " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", + " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", + " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", + " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", + " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", + " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", + " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", + " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", + " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", + " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + "\n", + "Number of Iterations....: 51\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", + "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", + "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "\n", + "\n", + "Number of objective function evaluations = 141\n", + "Number of objective gradient evaluations = 47\n", + "Number of equality constraint evaluations = 141\n", + "Number of inequality constraint evaluations = 141\n", + "Number of equality constraint Jacobian evaluations = 55\n", + "Number of inequality constraint Jacobian evaluations = 55\n", + "Number of Lagrangian Hessian evaluations = 52\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", + "Total CPU secs in NLP function evaluations = 0.010\n", + "\n", + "EXIT: Solved To Acceptable Level.\n" + ] + } + ], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.321235Z", + "start_time": "2025-06-11T22:13:35.245545Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 312786.33834066667\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8377.0 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", + " temperature kelvin 301.88 362.93 362.93 \n", + " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188276578115882\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -56353. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", + " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", + " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", + " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", + " temperature kelvin 696.11 301.88 301.88 \n", + " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-11T22:13:35.405538Z", + "start_time": "2025-06-11T22:13:35.398221Z" + } + }, + "source": [ + "print(f'''Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "''')" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 696.112 K\n", + "\n", + "F101 outlet temperature = 301.878 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file From c6d88954aef8ca423a16dab16c3ad5d3e50db43a Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 12 Jun 2025 18:37:53 -0600 Subject: [PATCH 29/36] Flash Unite and HDA Flowsheet Tutorial Revisions to reflect changes to initialization and scaling --- .../notebooks/docs/tut/core/flash_unit.ipynb | 1 + .../docs/tut/core/flash_unit_doc.ipynb | 1 + .../docs/tut/core/flash_unit_exercise.ipynb | 1 + .../docs/tut/core/flash_unit_solution.ipynb | 1 + .../docs/tut/core/flash_unit_test.ipynb | 1 + .../docs/tut/core/flash_unit_usr.ipynb | 1 + .../docs/tut/core/hda_flowsheet.ipynb | 107 ++++++++++-------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 103 +++++++++-------- .../tut/core/hda_flowsheet_exercise.ipynb | 105 +++++++++-------- .../tut/core/hda_flowsheet_solution.ipynb | 107 ++++++++++-------- .../docs/tut/core/hda_flowsheet_test.ipynb | 103 +++++++++-------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 107 ++++++++++-------- 12 files changed, 347 insertions(+), 291 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index 2fe01927..b01b3183 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 5f3b9777..27292328 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 7c93163d..8f3789d9 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 0e823872..0557e0df 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 62609b47..9bce54d7 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 0e823872..0557e0df 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -90,6 +90,7 @@ "\n", "# Import idaes logger to set output levels\n", "import idaes.logger as idaeslog\n", + "\n", "%matplotlib inline" ], "outputs": [], diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 2fca2a80..af8206a3 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1411,9 +1409,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1433,7 +1431,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1511,7 +1509,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1549,27 +1546,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1938,7 +1941,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1973,10 +1978,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2036,7 +2041,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2250,7 +2255,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2278,7 +2285,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -3133,7 +3140,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -3143,7 +3151,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 329c0c99..be783094 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -348,11 +351,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -472,14 +473,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -557,7 +555,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1204,9 +1202,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1226,7 +1224,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1304,7 +1302,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1342,27 +1339,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1731,7 +1734,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1766,10 +1771,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1791,7 +1796,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -1977,7 +1982,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2639,7 +2644,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2649,7 +2655,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 91c14462..6a51e39c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -347,11 +350,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -485,14 +486,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -583,7 +581,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1272,9 +1270,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1294,7 +1292,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1372,7 +1370,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1410,27 +1407,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1799,7 +1802,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1834,10 +1839,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1906,7 +1911,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -1934,7 +1941,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2639,7 +2646,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2649,7 +2657,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 7e8b3ff6..0d19ffad 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1375,9 +1373,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1397,7 +1395,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1475,7 +1473,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1513,27 +1510,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1902,7 +1905,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1937,10 +1942,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2000,7 +2005,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2194,7 +2199,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2222,7 +2229,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2984,7 +2991,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2994,7 +3002,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 14dbf8bc..16908e20 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -348,11 +351,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -472,14 +473,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -557,7 +555,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1240,9 +1238,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1262,7 +1260,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1340,7 +1338,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1378,27 +1375,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1767,7 +1770,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1802,10 +1807,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -1827,7 +1832,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2033,7 +2038,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2788,7 +2793,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2798,7 +2804,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 7e8b3ff6..0d19ffad 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -180,9 +180,12 @@ }, "source": [ "from idaes.models.unit_models import (\n", - " PressureChanger, IsentropicPressureChangerInitializer,\n", - " Mixer, MixerInitializer,\n", - " Separator as Splitter, SeparatorInitializer,\n", + " PressureChanger,\n", + " IsentropicPressureChangerInitializer,\n", + " Mixer,\n", + " MixerInitializer,\n", + " Separator as Splitter,\n", + " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", @@ -365,11 +368,9 @@ } }, "source": [ - "m.fs.I101 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.I102 = Feed(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", " property_package=m.fs.thermo_params,\n", @@ -527,14 +528,11 @@ }, "cell_type": "code", "source": [ - "m.fs.P101 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P102 = Product(\n", - " property_package=m.fs.thermo_params)\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", "\n", - "m.fs.P103 = Product(\n", - " property_package=m.fs.thermo_params)" + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], "execution_count": 16 @@ -643,7 +641,7 @@ "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)\n" + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], "execution_count": 20 @@ -1375,9 +1373,9 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "### 5.2 Manual Propogation Method\n", + "### 5.2 Manual Propagation Method\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initalizer method and propogating manually throught the flowsheet and solving for the tear stream directly.\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", "Lets first import a helper function that will help us manually propagate and step through the flowsheet" ] }, @@ -1397,7 +1395,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually intialize the model.\n", + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", "We will first ensure that are current degrees of freedom is still zero" ] @@ -1475,7 +1473,6 @@ " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.02,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - "\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1513,27 +1510,33 @@ }, "cell_type": "code", "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "propagate_state(\n", + " m.fs.s07\n", + ") # Establish connection between First Flash Unit and Second Flash Unit\n", + "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "propagate_state(\n", + " m.fs.s10\n", + ") # Establish connection between Second Flash Unit and Benzene Product\n", + "propagate_state(\n", + " m.fs.s11\n", + ") # Establish connection between Second Flash Unit and Toluene Product\n", + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1902,7 +1905,9 @@ " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", "\n", "m.fs.s03_expanded.activate()\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\")" + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" ], "outputs": [ { @@ -1937,10 +1942,10 @@ "cell_type": "code", "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 500,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 500,\n", + " \"tol\": 1e-8,\n", "}" ], "outputs": [], @@ -2000,7 +2005,7 @@ "solver = get_solver(solver_options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)\n" + "results = solver.solve(m, tee=True)" ], "outputs": [ { @@ -2194,7 +2199,9 @@ } }, "cell_type": "code", - "source": "m.fs.visualize('HDA-Flowsheet')", + "source": [ + "m.fs.visualize(\"HDA-Flowsheet\")" + ], "outputs": [ { "name": "stdout", @@ -2222,7 +2229,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recomended to adjust the width of the output as much as possible for the cleanest display." + "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." }, { "metadata": { @@ -2984,7 +2991,8 @@ } }, "source": [ - "print(f'''Optimal Values:\n", + "print(\n", + " f\"\"\"Optimal Values:\n", "\n", "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", "\n", @@ -2994,7 +3002,8 @@ "\n", "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "''')" + "\"\"\"\n", + ")" ], "outputs": [ { From aff22400a1823e858cf2dff2c4d9fbfee906833e Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Fri, 13 Jun 2025 17:14:09 -0600 Subject: [PATCH 30/36] Updated version numbers for GitHub Actions to version 4 --- .github/workflows/core.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index c9c7e1bf..9c71c7e4 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -69,7 +69,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run Spell Checker uses: crate-ci/typos@master @@ -95,7 +95,7 @@ jobs: - os: win64 runner-image: windows-2022 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Conda environment uses: conda-incubator/setup-miniconda@v2.2.0 with: From 2552c8f79c9ebce59765fe3381c65d04097fc768 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Tue, 24 Jun 2025 13:55:11 -0700 Subject: [PATCH 31/36] Revised both Tutorials based on feedback and ensured they both work as intended --- .../notebooks/docs/tut/core/HDA_flowsheet.png | Bin 52808 -> 85876 bytes .../notebooks/docs/tut/core/flash_unit.ipynb | 28 +- .../docs/tut/core/flash_unit_doc.ipynb | 28 +- .../docs/tut/core/flash_unit_exercise.ipynb | 28 +- .../docs/tut/core/flash_unit_solution.ipynb | 28 +- .../docs/tut/core/flash_unit_test.ipynb | 28 +- .../docs/tut/core/flash_unit_usr.ipynb | 28 +- .../docs/tut/core/hda_flowsheet.ipynb | 1390 ++++++++--------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 1277 +++++++-------- .../tut/core/hda_flowsheet_exercise.ipynb | 946 +++++------ .../tut/core/hda_flowsheet_solution.ipynb | 1354 ++++++++-------- .../docs/tut/core/hda_flowsheet_test.ipynb | 1313 ++++++++-------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 1354 ++++++++-------- 13 files changed, 3831 insertions(+), 3971 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/HDA_flowsheet.png b/idaes_examples/notebooks/docs/tut/core/HDA_flowsheet.png index 837bafb5eb57c210d7a56baf5df40d5452f15b47..e3a20f5fd2543f20a770bc2b2322226e4ad2cb18 100644 GIT binary patch literal 85876 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ð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 literal 52808 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 B#)$v` diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index b01b3183..a44b3af3 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -608,7 +608,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -695,7 +695,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 27292328..07569d68 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -220,7 +220,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -481,7 +481,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -534,7 +534,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 8f3789d9..81943bc9 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -164,7 +164,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -216,7 +216,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -490,7 +490,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -551,7 +551,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index 0557e0df..bf8397d4 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -590,7 +590,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -677,7 +677,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 9bce54d7..723382dd 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -220,7 +220,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -499,7 +499,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -552,7 +552,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index 0557e0df..bf8397d4 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -41,17 +41,17 @@ "\n", "In this module, we will familiarize ourselves with the IDAES framework by creating and working with a flowsheet that contains a single flash tank. The flash tank will be used to perform separation of Benzene and Toluene.\n", "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", + "The general workflow of setting up an IDAES flowsheet is the following:
\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "## Key links to documentation\n", "* Main IDAES online documentation page: https://idaes-pse.readthedocs.io/en/stable/\n", @@ -68,7 +68,7 @@ "\n", "In the next cell, we will perform the necessary imports to get us started. From `pyomo.environ` (a standard import for the Pyomo package), we are importing `ConcreteModel` (to create the Pyomo model that will contain the IDAES flowsheet) and `SolverFactory` (to create the object we will use to solve the equations). We will also import `Constraint` as we will be adding a constraint to the model later in the module. Lastly, we also import `value` from Pyomo. This is a function that can be used to return the current numerical value for variables and parameters in the model. These are all part of Pyomo.\n", "\n", - "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model.\n", + "We will also import the main `FlowsheetBlock` from IDAES. The flowsheet block will contain our unit model. `%matplotinline` allows plots to be displayed within the jupyter cell block output rather than in a separate window.\n", "\n", "
\n", "Inline Exercise:\n", @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module.\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", @@ -251,7 +251,7 @@ "\n", "**The Unit Model Library within IDAES includes a large set of common unit operations (see the online documentation for details: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html**\n", "\n", - "IDAES also fully supports the development of customized unit models (which we will see in a later module).\n", + "IDAES also fully supports the development of customized unit models (which we will see in a later module). More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/unit_models/custom_unit_models/index.html.\n", "\n", "Some of the IDAES pre-written unit models:\n", "* Mixer / Splitter\n", @@ -590,7 +590,7 @@ "\n", "
\n", "Note:\n", - "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a timestep. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single timestep in the model.\n", + "The \"0\" in the indexing of the component mole fraction is present because IDAES models support both dynamic and steady state simulation, and the \"0\" refers to a time point. Dynamic modeling is beyond the scope of this workshop. Since we are performing steady state modeling, there is only a single time point in the model.\n", "
\n", "\n", "In the next cell, we will specify the inlet conditions. To satisfy the remaining degrees of freedom, we will make two additional specifications on the flash tank itself. The names of the key variables within the Flash unit model can also be found in the online documentation: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/flash.html#variables.\n", @@ -677,7 +677,7 @@ "metadata": {}, "cell_type": "markdown", "source": [ - "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0\n", + "Now that all the inlets have been specified, we can check the degrees of freedom again to ensure the system is square and has a degree of freedom of 0.\n", "\n" ] }, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index af8206a3..ec841572 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -879,8 +882,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.996567Z", - "start_time": "2025-06-11T22:13:28.973555Z" + "end_time": "2025-06-24T19:31:55.360025Z", + "start_time": "2025-06-24T19:31:55.338112Z" } }, "source": [ @@ -893,14 +896,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -938,8 +943,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -970,8 +975,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -991,8 +996,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1023,8 +1028,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1061,8 +1066,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1078,8 +1083,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1100,8 +1105,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1134,8 +1139,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1151,8 +1156,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1176,8 +1181,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.304978Z", - "start_time": "2025-06-11T22:13:29.282394Z" + "end_time": "2025-06-24T19:31:55.652507Z", + "start_time": "2025-06-24T19:31:55.628692Z" } }, "source": [ @@ -1188,17 +1193,17 @@ "execution_count": 40 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1221,20 +1226,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1262,8 +1269,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1293,8 +1300,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1333,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1370,8 +1377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1397,17 +1404,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1416,20 +1425,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1437,14 +1448,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1457,18 +1470,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1486,18 +1501,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1507,7 +1524,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1533,19 +1550,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1572,54 +1592,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1629,9 +1657,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1669,272 +1700,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1957,30 +1774,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1988,12 +1809,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -2013,8 +1834,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -2032,8 +1853,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2052,10 +1873,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2093,116 +1914,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2217,8 +2220,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.344624Z", - "start_time": "2025-06-11T22:13:32.341522Z" + "end_time": "2025-06-24T19:31:58.324104Z", + "start_time": "2025-06-24T19:31:58.321662Z" } }, "source": [ @@ -2240,62 +2243,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2307,8 +2295,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2324,16 +2312,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2344,7 +2334,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2357,8 +2347,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.166006Z", - "start_time": "2025-06-11T22:13:34.094011Z" + "end_time": "2025-06-24T19:31:58.533714Z", + "start_time": "2025-06-24T19:31:58.461636Z" } }, "source": [ @@ -2372,14 +2362,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2420,7 +2412,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2433,8 +2425,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.213201Z", - "start_time": "2025-06-11T22:13:34.210228Z" + "end_time": "2025-06-24T19:31:58.576962Z", + "start_time": "2025-06-24T19:31:58.573769Z" } }, "source": [ @@ -2448,14 +2440,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2473,8 +2467,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2521,8 +2515,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2542,8 +2536,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2579,8 +2573,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2596,8 +2590,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2614,8 +2608,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.535666Z", - "start_time": "2025-06-11T22:13:34.502099Z" + "end_time": "2025-06-24T19:31:58.762582Z", + "start_time": "2025-06-24T19:31:58.737160Z" } }, "source": [ @@ -2643,8 +2637,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2677,8 +2671,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2694,8 +2688,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2717,8 +2711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2743,8 +2737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2779,8 +2773,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2796,8 +2790,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2820,8 +2814,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2844,8 +2838,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2860,10 +2854,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2917,67 +2911,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2992,8 +2992,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.223076Z", - "start_time": "2025-06-11T22:13:35.219792Z" + "end_time": "2025-06-24T19:31:59.213739Z", + "start_time": "2025-06-24T19:31:59.210358Z" } }, "source": [ @@ -3018,8 +3018,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -3042,7 +3042,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -3072,7 +3072,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -3113,8 +3113,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.348144Z", - "start_time": "2025-06-11T22:13:35.343061Z" + "end_time": "2025-06-24T19:31:59.287634Z", + "start_time": "2025-06-24T19:31:59.283037Z" } }, "source": [ @@ -3135,8 +3135,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3182,8 +3182,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.448075Z", - "start_time": "2025-06-11T22:13:35.443091Z" + "end_time": "2025-06-24T19:31:59.345387Z", + "start_time": "2025-06-24T19:31:59.340713Z" } }, "source": [ @@ -3214,7 +3214,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index be783094..6434a3ca 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -291,15 +291,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -426,14 +426,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -460,18 +462,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -488,17 +492,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -507,16 +518,6 @@ "outputs": [], "execution_count": 17 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, { "cell_type": "code", "metadata": { @@ -524,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -546,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -561,18 +562,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -592,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -608,7 +611,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -624,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -651,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -680,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -703,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -716,8 +719,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -731,13 +734,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -768,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -789,14 +792,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -834,8 +839,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -866,8 +871,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -887,8 +892,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -919,8 +924,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -937,8 +942,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -959,8 +964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -977,8 +982,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1014,20 +1019,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1055,8 +1062,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1086,8 +1093,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1126,8 +1133,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1163,8 +1170,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1190,17 +1197,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1209,20 +1218,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1230,14 +1241,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1250,18 +1263,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1279,18 +1294,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1300,7 +1317,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1326,19 +1343,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1365,54 +1385,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1422,9 +1450,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1462,272 +1493,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1750,30 +1567,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1787,8 +1608,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -1807,10 +1628,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1848,116 +1669,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -1975,24 +1978,30 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2004,8 +2013,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2021,16 +2030,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2041,7 +2052,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2050,14 +2061,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2098,7 +2111,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2107,14 +2120,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2132,8 +2147,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2180,8 +2195,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2201,8 +2216,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2221,8 +2236,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2251,8 +2266,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2269,8 +2284,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2292,8 +2307,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2318,8 +2333,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2338,8 +2353,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2362,8 +2377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2386,8 +2401,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2402,10 +2417,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2459,67 +2474,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2540,8 +2561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2564,7 +2585,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2594,7 +2615,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2639,8 +2660,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2697,7 +2718,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 6a51e39c..4b548c13 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -233,8 +233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -273,8 +273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -290,15 +290,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -319,8 +319,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -345,8 +345,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -396,8 +396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -422,8 +422,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -439,14 +439,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -473,18 +475,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -501,17 +505,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -522,21 +533,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -551,8 +552,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -572,8 +573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -587,18 +588,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -618,8 +621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -634,7 +637,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -650,8 +653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -677,8 +680,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -706,8 +709,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -729,8 +732,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -742,8 +745,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -757,13 +760,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -794,8 +797,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -815,14 +818,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -860,8 +865,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -892,8 +897,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -913,8 +918,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -945,8 +950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -983,8 +988,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1004,8 +1009,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1038,8 +1043,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1049,17 +1054,17 @@ "execution_count": 38 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1082,20 +1087,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1123,8 +1130,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1154,8 +1161,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1194,8 +1201,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1231,8 +1238,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1258,17 +1265,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1277,20 +1286,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1298,14 +1309,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1318,18 +1331,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1347,18 +1362,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1368,7 +1385,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1394,19 +1411,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1433,54 +1453,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1490,9 +1518,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1530,272 +1561,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1818,30 +1635,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1849,12 +1670,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1874,8 +1695,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1896,62 +1717,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -1963,8 +1769,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -1980,16 +1786,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2000,7 +1808,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2009,14 +1817,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2057,7 +1867,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2066,14 +1876,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2091,8 +1903,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2139,8 +1951,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2160,8 +1972,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2197,8 +2009,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2226,8 +2038,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2260,8 +2072,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2281,8 +2093,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2307,8 +2119,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2343,8 +2155,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2364,8 +2176,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2388,8 +2200,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2404,10 +2216,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2461,67 +2273,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2542,8 +2360,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2566,7 +2384,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2596,7 +2414,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2641,8 +2459,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2699,7 +2517,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 0d19ffad..1f252838 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -875,14 +878,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -920,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -952,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -973,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1005,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1043,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1060,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1082,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1116,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1133,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1152,17 +1157,17 @@ "execution_count": 39 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1185,20 +1190,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1226,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1257,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1297,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1334,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1361,17 +1368,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1380,20 +1389,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1401,14 +1412,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1421,18 +1434,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1450,18 +1465,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1471,7 +1488,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1497,19 +1514,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1536,54 +1556,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1593,9 +1621,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1633,272 +1664,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1921,30 +1738,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1952,12 +1773,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1977,8 +1798,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1996,8 +1817,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2016,10 +1837,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2057,116 +1878,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2184,62 +2187,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2251,8 +2239,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2268,16 +2256,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2288,7 +2278,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2297,14 +2287,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2345,7 +2337,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2354,14 +2346,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2379,8 +2373,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2427,8 +2421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2448,8 +2442,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2485,8 +2479,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2502,8 +2496,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2532,8 +2526,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2566,8 +2560,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2583,8 +2577,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2606,8 +2600,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2632,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2668,8 +2662,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2685,8 +2679,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2709,8 +2703,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2733,8 +2727,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2749,10 +2743,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2806,67 +2800,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2887,8 +2887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2911,7 +2911,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2941,7 +2941,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2986,8 +2986,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3044,7 +3044,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 16908e20..de891a01 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -291,15 +291,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -426,14 +426,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -460,18 +462,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -488,17 +492,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -507,16 +518,6 @@ "outputs": [], "execution_count": 17 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, { "cell_type": "code", "metadata": { @@ -524,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -546,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -561,18 +562,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -592,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -608,7 +611,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -624,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -651,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -680,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -703,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -716,8 +719,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -731,13 +734,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -768,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -793,8 +796,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.996567Z", - "start_time": "2025-06-11T22:13:28.973555Z" + "end_time": "2025-06-24T19:31:55.360025Z", + "start_time": "2025-06-24T19:31:55.338112Z" } }, "source": [ @@ -807,14 +810,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -852,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -884,8 +889,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -905,8 +910,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -937,8 +942,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -955,8 +960,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -977,8 +982,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -995,8 +1000,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1020,8 +1025,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.304978Z", - "start_time": "2025-06-11T22:13:29.282394Z" + "end_time": "2025-06-24T19:31:55.652507Z", + "start_time": "2025-06-24T19:31:55.628692Z" } }, "source": [ @@ -1050,20 +1055,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1091,8 +1098,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1122,8 +1129,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1162,8 +1169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1199,8 +1206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1226,17 +1233,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1245,20 +1254,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1266,14 +1277,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1286,18 +1299,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1315,18 +1330,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1336,7 +1353,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1362,19 +1379,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1401,54 +1421,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1458,9 +1486,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1498,272 +1529,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1786,30 +1603,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1823,8 +1644,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -1843,10 +1664,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1884,116 +1705,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2008,8 +2011,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.344624Z", - "start_time": "2025-06-11T22:13:32.341522Z" + "end_time": "2025-06-24T19:31:58.324104Z", + "start_time": "2025-06-24T19:31:58.321662Z" } }, "source": [ @@ -2031,24 +2034,30 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2060,8 +2069,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2077,16 +2086,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2097,7 +2108,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2110,8 +2121,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.166006Z", - "start_time": "2025-06-11T22:13:34.094011Z" + "end_time": "2025-06-24T19:31:58.533714Z", + "start_time": "2025-06-24T19:31:58.461636Z" } }, "source": [ @@ -2125,14 +2136,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2173,7 +2186,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2186,8 +2199,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.213201Z", - "start_time": "2025-06-11T22:13:34.210228Z" + "end_time": "2025-06-24T19:31:58.576962Z", + "start_time": "2025-06-24T19:31:58.573769Z" } }, "source": [ @@ -2201,14 +2214,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2226,8 +2241,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2274,8 +2289,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2295,8 +2310,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2315,8 +2330,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2333,8 +2348,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.535666Z", - "start_time": "2025-06-11T22:13:34.502099Z" + "end_time": "2025-06-24T19:31:58.762582Z", + "start_time": "2025-06-24T19:31:58.737160Z" } }, "source": [ @@ -2362,8 +2377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2380,8 +2395,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2403,8 +2418,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2429,8 +2444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2449,8 +2464,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2473,8 +2488,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2497,8 +2512,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2513,10 +2528,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2570,67 +2585,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2645,8 +2666,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.223076Z", - "start_time": "2025-06-11T22:13:35.219792Z" + "end_time": "2025-06-24T19:31:59.213739Z", + "start_time": "2025-06-24T19:31:59.210358Z" } }, "source": [ @@ -2671,8 +2692,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2695,7 +2716,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2725,7 +2746,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2766,8 +2787,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.348144Z", - "start_time": "2025-06-11T22:13:35.343061Z" + "end_time": "2025-06-24T19:31:59.287634Z", + "start_time": "2025-06-24T19:31:59.283037Z" } }, "source": [ @@ -2788,8 +2809,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -2835,8 +2856,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.448075Z", - "start_time": "2025-06-11T22:13:35.443091Z" + "end_time": "2025-06-24T19:31:59.345387Z", + "start_time": "2025-06-24T19:31:59.340713Z" } }, "source": [ @@ -2867,7 +2888,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 0d19ffad..1f252838 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -8,14 +8,14 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:25.418463Z", - "start_time": "2025-06-11T22:13:25.412645Z" + "end_time": "2025-06-24T19:31:51.625798Z", + "start_time": "2025-06-24T19:31:51.621877Z" } }, "source": [ "###############################################################################\n", "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (IDAES IP) was produced under the DOE Institute for the\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", "# Design of Advanced Energy Systems (IDAES).\n", "#\n", "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", @@ -54,16 +54,16 @@ "\n", "The general workflow of setting up an IDAES flowsheet is the following:\n", "\n", - "- 1 Importing Modules\n", - "- 2 Building a Model\n", - "- 3 Scaling the Model\n", - "- 4 Specifying the Model\n", - "- 5 Initializing the Model\n", - "- 6 Solving the Model\n", - "- 7 Analyzing and Visualizing the Results\n", - "- 8 Optimizing the Model\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", "\n", "\n", "## Problem Statement\n", @@ -100,10 +100,10 @@ "metadata": {}, "source": [ "## 1 Importing Modules\n", - "### 1.1 Importing required pyomo and idaes components\n", + "### 1.1 Importing required Pyomo and IDAES components\n", "\n", "\n", - "To construct a flowsheet, we will need several components from the pyomo and idaes package. Let us first import the following components from Pyomo:\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", "- Constraint (to write constraints)\n", "- Var (to declare variables)\n", "- ConcreteModel (to create the concrete model object)\n", @@ -114,15 +114,15 @@ "- Arc (to connect two unit models)\n", "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", "\n", - "For further details on these components, please refer to the pyomo documentation: https://pyomo.readthedocs.io/en/stable/\n" + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:26.066510Z", - "start_time": "2025-06-11T22:13:25.662098Z" + "end_time": "2025-06-24T19:31:52.254163Z", + "start_time": "2025-06-24T19:31:51.828427Z" } }, "source": [ @@ -145,7 +145,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "From idaes, we will be needing the FlowsheetBlock and the following unit models:\n", + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", "- Feed\n", "- Mixer\n", "- Heater\n", @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.637361Z", - "start_time": "2025-06-11T22:13:26.082580Z" + "end_time": "2025-06-24T19:31:54.053674Z", + "start_time": "2025-06-24T19:31:52.269805Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.752223Z", - "start_time": "2025-06-11T22:13:27.645348Z" + "end_time": "2025-06-24T19:31:54.167306Z", + "start_time": "2025-06-24T19:31:54.062903Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.763417Z", - "start_time": "2025-06-11T22:13:27.761004Z" + "end_time": "2025-06-24T19:31:54.179208Z", + "start_time": "2025-06-24T19:31:54.177035Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.774708Z", - "start_time": "2025-06-11T22:13:27.772299Z" + "end_time": "2025-06-24T19:31:54.191096Z", + "start_time": "2025-06-24T19:31:54.188112Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.788004Z", - "start_time": "2025-06-11T22:13:27.784891Z" + "end_time": "2025-06-24T19:31:54.207515Z", + "start_time": "2025-06-24T19:31:54.204470Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.806315Z", - "start_time": "2025-06-11T22:13:27.798068Z" + "end_time": "2025-06-24T19:31:54.224870Z", + "start_time": "2025-06-24T19:31:54.218012Z" } }, "source": [ @@ -308,15 +308,15 @@ "source": [ "## 2 Constructing the Flowsheet\n", "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block as we did in module 1. " + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.819615Z", - "start_time": "2025-06-11T22:13:27.814729Z" + "end_time": "2025-06-24T19:31:54.238662Z", + "start_time": "2025-06-24T19:31:54.233640Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.841949Z", - "start_time": "2025-06-11T22:13:27.829949Z" + "end_time": "2025-06-24T19:31:54.260417Z", + "start_time": "2025-06-24T19:31:54.248422Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.876870Z", - "start_time": "2025-06-11T22:13:27.853517Z" + "end_time": "2025-06-24T19:31:54.290806Z", + "start_time": "2025-06-24T19:31:54.268045Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.894702Z", - "start_time": "2025-06-11T22:13:27.891599Z" + "end_time": "2025-06-24T19:31:54.301750Z", + "start_time": "2025-06-24T19:31:54.299504Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.921265Z", - "start_time": "2025-06-11T22:13:27.910910Z" + "end_time": "2025-06-24T19:31:54.320004Z", + "start_time": "2025-06-24T19:31:54.309474Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.947463Z", - "start_time": "2025-06-11T22:13:27.933993Z" + "end_time": "2025-06-24T19:31:54.339399Z", + "start_time": "2025-06-24T19:31:54.328449Z" } }, "source": [ @@ -481,14 +481,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:27.987933Z", - "start_time": "2025-06-11T22:13:27.964931Z" + "end_time": "2025-06-24T19:31:54.368435Z", + "start_time": "2025-06-24T19:31:54.346808Z" } }, "source": [ @@ -515,18 +517,20 @@ "execution_count": 15 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.009893Z", - "start_time": "2025-06-11T22:13:28.001769Z" + "end_time": "2025-06-24T19:31:54.383971Z", + "start_time": "2025-06-24T19:31:54.375760Z" } }, - "cell_type": "code", "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -543,17 +547,24 @@ "source": [ "### 2.2 Connecting Unit Models using Arcs\n", "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.034324Z", - "start_time": "2025-06-11T22:13:28.031285Z" + "end_time": "2025-06-24T19:31:54.394877Z", + "start_time": "2025-06-24T19:31:54.391652Z" } }, - "cell_type": "code", "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", @@ -564,21 +575,11 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "![](HDA_flowsheet.png) \n", - "\n", - "\n" - ] - }, - { "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -593,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.055815Z", - "start_time": "2025-06-11T22:13:28.052507Z" + "end_time": "2025-06-24T19:31:54.406228Z", + "start_time": "2025-06-24T19:31:54.403906Z" } }, "source": [ @@ -610,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.084663Z", - "start_time": "2025-06-11T22:13:28.082008Z" + "end_time": "2025-06-24T19:31:54.417559Z", + "start_time": "2025-06-24T19:31:54.414462Z" } }, "source": [ @@ -632,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.118422Z", - "start_time": "2025-06-11T22:13:28.113732Z" + "end_time": "2025-06-24T19:31:54.434638Z", + "start_time": "2025-06-24T19:31:54.429537Z" } }, "source": [ @@ -647,18 +648,20 @@ "execution_count": 20 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.148879Z", - "start_time": "2025-06-11T22:13:28.144601Z" + "end_time": "2025-06-24T19:31:54.448099Z", + "start_time": "2025-06-24T19:31:54.444761Z" } }, - "cell_type": "code", "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", @@ -678,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.198384Z", - "start_time": "2025-06-11T22:13:28.176239Z" + "end_time": "2025-06-24T19:31:54.480416Z", + "start_time": "2025-06-24T19:31:54.459619Z" } }, "source": [ @@ -694,7 +697,7 @@ "source": [ "### 2.3 Adding expressions to compute purity and operating costs\n", "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Expressions.html\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", "\n", "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " ] @@ -710,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.222088Z", - "start_time": "2025-06-11T22:13:28.218400Z" + "end_time": "2025-06-24T19:31:54.491966Z", + "start_time": "2025-06-24T19:31:54.488552Z" } }, "source": [ @@ -737,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.248216Z", - "start_time": "2025-06-11T22:13:28.244244Z" + "end_time": "2025-06-24T19:31:54.510661Z", + "start_time": "2025-06-24T19:31:54.507100Z" } }, "source": [ @@ -766,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.271256Z", - "start_time": "2025-06-11T22:13:28.268284Z" + "end_time": "2025-06-24T19:31:54.534099Z", + "start_time": "2025-06-24T19:31:54.531585Z" } }, "source": [ @@ -789,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.295580Z", - "start_time": "2025-06-11T22:13:28.292627Z" + "end_time": "2025-06-24T19:31:54.557278Z", + "start_time": "2025-06-24T19:31:54.554745Z" } }, "source": [ @@ -802,8 +805,8 @@ "execution_count": 26 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "## 3 Scaling the Model\n", "\n", @@ -817,13 +820,13 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.915668Z", - "start_time": "2025-06-11T22:13:28.317020Z" + "end_time": "2025-06-24T19:31:55.298145Z", + "start_time": "2025-06-24T19:31:54.575470Z" } }, - "cell_type": "code", "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" @@ -854,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:28.948173Z", - "start_time": "2025-06-11T22:13:28.924210Z" + "end_time": "2025-06-24T19:31:55.328653Z", + "start_time": "2025-06-24T19:31:55.306276Z" } }, "source": [ @@ -875,14 +878,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.012096Z", - "start_time": "2025-06-11T22:13:29.006965Z" + "end_time": "2025-06-24T19:31:55.377191Z", + "start_time": "2025-06-24T19:31:55.372584Z" } }, "source": [ @@ -920,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.036253Z", - "start_time": "2025-06-11T22:13:29.031731Z" + "end_time": "2025-06-24T19:31:55.398733Z", + "start_time": "2025-06-24T19:31:55.393659Z" } }, "source": [ @@ -952,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.078559Z", - "start_time": "2025-06-11T22:13:29.075531Z" + "end_time": "2025-06-24T19:31:55.421506Z", + "start_time": "2025-06-24T19:31:55.418367Z" } }, "source": [ @@ -973,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.111099Z", - "start_time": "2025-06-11T22:13:29.106956Z" + "end_time": "2025-06-24T19:31:55.453218Z", + "start_time": "2025-06-24T19:31:55.448353Z" } }, "source": [ @@ -1005,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.128972Z", - "start_time": "2025-06-11T22:13:29.125273Z" + "end_time": "2025-06-24T19:31:55.477166Z", + "start_time": "2025-06-24T19:31:55.473650Z" } }, "source": [ @@ -1043,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.149002Z", - "start_time": "2025-06-11T22:13:29.146476Z" + "end_time": "2025-06-24T19:31:55.503091Z", + "start_time": "2025-06-24T19:31:55.500190Z" } }, "source": [ @@ -1060,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.171742Z", - "start_time": "2025-06-11T22:13:29.168352Z" + "end_time": "2025-06-24T19:31:55.544924Z", + "start_time": "2025-06-24T19:31:55.541593Z" } }, "source": [ @@ -1082,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.196247Z", - "start_time": "2025-06-11T22:13:29.192956Z" + "end_time": "2025-06-24T19:31:55.563038Z", + "start_time": "2025-06-24T19:31:55.560499Z" } }, "source": [ @@ -1116,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.220402Z", - "start_time": "2025-06-11T22:13:29.217907Z" + "end_time": "2025-06-24T19:31:55.579334Z", + "start_time": "2025-06-24T19:31:55.577111Z" } }, "source": [ @@ -1133,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.263397Z", - "start_time": "2025-06-11T22:13:29.241129Z" + "end_time": "2025-06-24T19:31:55.624668Z", + "start_time": "2025-06-24T19:31:55.601688Z" } }, "source": [ @@ -1152,17 +1157,17 @@ "execution_count": 39 }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.316042Z", - "start_time": "2025-06-11T22:13:29.313537Z" + "end_time": "2025-06-24T19:31:55.664812Z", + "start_time": "2025-06-24T19:31:55.662484Z" } }, - "cell_type": "code", - "source": "", + "source": [], "outputs": [], "execution_count": null }, @@ -1185,20 +1190,22 @@ "\n", "### 5.1 Sequential Decomposition\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from pyomo where the documentation can be found here https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" ] }, { "cell_type": "markdown", "metadata": {}, - "source": "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.330212Z", - "start_time": "2025-06-11T22:13:29.324872Z" + "end_time": "2025-06-24T19:31:55.683525Z", + "start_time": "2025-06-24T19:31:55.678196Z" } }, "source": [ @@ -1226,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.353734Z", - "start_time": "2025-06-11T22:13:29.350730Z" + "end_time": "2025-06-24T19:31:55.701611Z", + "start_time": "2025-06-24T19:31:55.698137Z" } }, "source": [ @@ -1257,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.391173Z", - "start_time": "2025-06-11T22:13:29.388153Z" + "end_time": "2025-06-24T19:31:55.722499Z", + "start_time": "2025-06-24T19:31:55.719447Z" } }, "source": [ @@ -1297,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.430684Z", - "start_time": "2025-06-11T22:13:29.426921Z" + "end_time": "2025-06-24T19:31:55.752786Z", + "start_time": "2025-06-24T19:31:55.746899Z" } }, "source": [ @@ -1334,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.465203Z", - "start_time": "2025-06-11T22:13:29.462031Z" + "end_time": "2025-06-24T19:31:55.778192Z", + "start_time": "2025-06-24T19:31:55.774682Z" } }, "source": [ @@ -1361,17 +1368,19 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.505027Z", - "start_time": "2025-06-11T22:13:29.501933Z" + "end_time": "2025-06-24T19:31:55.795822Z", + "start_time": "2025-06-24T19:31:55.793437Z" } }, - "source": "# seq.run(m, function)", + "source": [ + "# seq.run(m, function)" + ], "outputs": [], "execution_count": 46 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "### 5.2 Manual Propagation Method\n", "\n", @@ -1380,20 +1389,22 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.536579Z", - "start_time": "2025-06-11T22:13:29.533074Z" + "end_time": "2025-06-24T19:31:55.816947Z", + "start_time": "2025-06-24T19:31:55.814431Z" } }, - "cell_type": "code", - "source": "from idaes.core.util.initialization import propagate_state", + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], "outputs": [], "execution_count": 47 }, { - "metadata": {}, "cell_type": "markdown", + "metadata": {}, "source": [ "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", @@ -1401,14 +1412,16 @@ ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.583098Z", - "start_time": "2025-06-11T22:13:29.553382Z" + "end_time": "2025-06-24T19:31:55.860044Z", + "start_time": "2025-06-24T19:31:55.834336Z" } }, - "cell_type": "code", - "source": "print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "source": [ + "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ], "outputs": [ { "name": "stdout", @@ -1421,18 +1434,20 @@ "execution_count": 48 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.633917Z", - "start_time": "2025-06-11T22:13:29.610932Z" + "end_time": "2025-06-24T19:31:55.885959Z", + "start_time": "2025-06-24T19:31:55.864176Z" } }, - "cell_type": "code", "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", @@ -1450,18 +1465,20 @@ "execution_count": 49 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:29.702707Z", - "start_time": "2025-06-11T22:13:29.654459Z" + "end_time": "2025-06-24T19:31:55.937458Z", + "start_time": "2025-06-24T19:31:55.892147Z" } }, - "cell_type": "code", "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1471,7 +1488,7 @@ " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", + " (0, \"Vap\", \"methane\"): 0.5,\n", " (0, \"Vap\", \"hydrogen\"): 0.30,\n", " },\n", " \"temperature\": {0: 303},\n", @@ -1497,19 +1514,22 @@ "execution_count": 50 }, { - "metadata": {}, "cell_type": "markdown", - "source": "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.347435Z", - "start_time": "2025-06-11T22:13:29.712721Z" + "end_time": "2025-06-24T19:31:57.330990Z", + "start_time": "2025-06-24T19:31:55.948780Z" } }, - "cell_type": "code", "source": [ + "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1536,54 +1556,62 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "2025-06-11 16:13:29 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-11 16:13:30 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-11 16:13:31 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], "execution_count": 51 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.935414Z", - "start_time": "2025-06-11T22:13:31.357025Z" + "end_time": "2025-06-24T19:31:57.422312Z", + "start_time": "2025-06-24T19:31:57.340180Z" } }, - "cell_type": "code", "source": [ - "solver = get_solver()\n", + "optarg = {\n", + " 'nlp_scaling_method': 'user-scaling',\n", + " 'OF_ma57_automatic_scaling': 'yes',\n", + " 'max_iter': 300,\n", + " 'tol': 1e-8,\n", + "}\n", + "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], "outputs": [ @@ -1593,9 +1621,12 @@ "text": [ "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=gradient-based\n", - "tol=1e-06\n", - "max_iter=200\n", + "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", + "tol=1e-08\n", + "max_iter=300\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1633,272 +1664,58 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.24e+05 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 1.24e+05 2.12e+00 -1.0 1.99e+05 - 1.39e-01 3.68e-04h 10\n", - " 2 0.0000000e+00 1.24e+05 5.49e+00 -1.0 1.99e+05 - 1.43e-01 3.66e-04h 10\n", - " 3 0.0000000e+00 1.24e+05 4.13e+01 -1.0 2.00e+05 - 9.51e-01 3.64e-04h 10\n", - " 4 0.0000000e+00 1.24e+05 7.47e+01 -1.0 2.00e+05 - 1.77e-01 3.63e-04h 10\n", - " 5 0.0000000e+00 1.24e+05 4.07e+02 -1.0 2.01e+05 - 9.90e-01 3.61e-04h 10\n", - " 6 0.0000000e+00 1.24e+05 6.97e+02 -1.0 2.01e+05 - 1.63e-01 3.60e-04h 10\n", - " 7 0.0000000e+00 1.24e+05 3.75e+03 -1.0 2.02e+05 - 9.90e-01 3.58e-04h 10\n", - " 8 0.0000000e+00 1.24e+05 6.44e+03 -1.0 2.02e+05 - 1.63e-01 3.57e-04h 10\n", - " 9 0.0000000e+00 1.24e+05 3.51e+04 -1.0 2.03e+05 - 1.00e+00 3.55e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.24e+05 6.05e+04 -1.0 2.04e+05 - 1.62e-01 3.54e-04h 10\n", - " 11 0.0000000e+00 2.01e+06 2.73e+05 -1.0 2.04e+05 - 1.00e+00 1.80e-01w 1\n", - " 12 0.0000000e+00 2.01e+06 3.91e+07 -1.0 7.38e+05 - 6.21e-02 5.22e-04w 1\n", - " 13 0.0000000e+00 2.01e+06 6.94e+11 -1.0 7.50e+05 - 9.13e-02 5.14e-06w 1\n", - " 14 0.0000000e+00 1.24e+05 3.32e+05 -1.0 6.22e+04 - 1.00e+00 3.52e-04h 9\n", - " 15 0.0000000e+00 1.24e+05 5.43e+05 -1.0 2.05e+05 - 1.41e-01 3.51e-04h 10\n", - " 16 0.0000000e+00 1.24e+05 3.01e+06 -1.0 2.05e+05 - 1.00e+00 3.49e-04h 10\n", - " 17 0.0000000e+00 1.24e+05 4.76e+06 -1.0 2.06e+05 - 1.28e-01 3.48e-04h 10\n", - " 18 0.0000000e+00 1.24e+05 2.66e+07 -1.0 2.06e+05 - 1.00e+00 3.46e-04h 10\n", - " 19 0.0000000e+00 1.24e+05 4.23e+07 -1.0 2.07e+05 - 1.28e-01 3.45e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.24e+05 2.38e+08 -1.0 2.08e+05 - 1.00e+00 3.43e-04h 10\n", - " 21 0.0000000e+00 1.24e+05 3.80e+08 -1.0 2.08e+05 - 1.28e-01 3.42e-04h 10\n", - " 22 0.0000000e+00 1.23e+05 2.16e+09 -1.0 2.09e+05 - 1.00e+00 3.40e-04h 10\n", - " 23 0.0000000e+00 1.23e+05 3.45e+09 -1.0 2.09e+05 - 1.28e-01 3.39e-04h 10\n", - " 24 0.0000000e+00 1.96e+06 1.26e+10 -1.0 2.10e+05 - 7.69e-01 1.73e-01w 1\n", - " 25 0.0000000e+00 1.96e+06 1.91e+12 -1.0 7.43e+05 - 6.14e-02 5.08e-04w 1\n", - " 26 0.0000000e+00 1.96e+06 7.01e+16 -1.0 7.55e+05 - 1.84e-01 5.01e-06w 1\n", - " 27 0.0000000e+00 1.23e+05 1.60e+10 -1.0 1.00e+05 - 7.69e-01 3.37e-04h 9\n", - " 28 0.0000000e+00 1.23e+05 2.61e+10 -1.0 2.10e+05 - 1.33e-01 3.36e-04h 10\n", - " 29 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.00e+00 3.35e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.11e+05 - 1.27e-01 3.33e-04h 10\n", - " 31 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.12e+05 - 5.83e-01 3.32e-04h 10\n", - " 32 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.41e-01 3.30e-04h 10\n", - " 33 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.13e+05 - 1.00e+00 3.29e-04h 10\n", - " 34 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 1.26e-01 3.28e-04h 10\n", - " 35 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.14e+05 - 6.16e-01 3.26e-04h 10\n", - " 36 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.15e+05 - 1.38e-01 3.25e-04h 10\n", - " 37 0.0000000e+00 1.90e+06 5.27e+11 -1.0 2.15e+05 - 1.00e+00 1.66e-01w 1\n", - " 38 0.0000000e+00 1.90e+06 6.09e+13 -1.0 2.72e+05 - 1.39e-01 1.43e-03w 1\n", - " 39 0.0000000e+00 1.90e+06 1.06e+17 -1.0 7.68e+05 - 9.45e-02 4.82e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.68e+05 - 1.00e+00 3.23e-04h 9\n", - " 41 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.16e+05 - 1.26e-01 3.22e-04h 10\n", - " 42 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 6.03e-01 3.21e-04h 10\n", - " 43 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.17e+05 - 1.38e-01 3.19e-04h 10\n", - " 44 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.00e+00 3.18e-04h 10\n", - " 45 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.18e+05 - 1.25e-01 3.17e-04h 10\n", - " 46 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.19e+05 - 6.03e-01 3.15e-04h 10\n", - " 47 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.38e-01 3.14e-04h 10\n", - " 48 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.20e+05 - 1.00e+00 3.13e-04h 10\n", - " 49 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.21e+05 - 1.25e-01 3.11e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 0.0000000e+00 1.85e+06 3.37e+11 -1.0 2.21e+05 - 5.99e-01 1.59e-01w 1\n", - " 51 0.0000000e+00 1.85e+06 5.67e+13 -1.0 7.53e+05 - 6.18e-02 4.82e-04w 1\n", - " 52 0.0000000e+00 1.85e+06 1.08e+17 -1.0 7.64e+05 - 2.20e-01 4.75e-06w 1\n", - " 53 0.0000000e+00 1.23e+05 1.04e+11 -1.0 7.64e+05 - 5.99e-01 3.10e-04h 9\n", - " 54 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.38e-01 3.09e-04h 10\n", - " 55 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.22e+05 - 1.00e+00 3.07e-04h 10\n", - " 56 0.0000000e+00 1.23e+05 1.04e+11 -1.0 2.23e+05 - 1.24e-01 3.06e-04h 10\n", - " 57 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 5.97e-01 3.05e-04h 10\n", - " 58 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.24e+05 - 1.37e-01 3.04e-04h 10\n", - " 59 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.00e+00 3.02e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.25e+05 - 1.24e-01 3.01e-04h 10\n", - " 61 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 5.94e-01 3.00e-04h 10\n", - " 62 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.26e+05 - 1.37e-01 2.98e-04h 10\n", - " 63 0.0000000e+00 1.79e+06 6.03e+11 -1.0 2.27e+05 - 1.00e+00 1.52e-01w 1\n", - " 64 0.0000000e+00 1.79e+06 9.13e+13 -1.0 7.58e+05 - 6.05e-02 4.69e-04w 1\n", - " 65 0.0000000e+00 1.79e+06 1.10e+17 -1.0 7.68e+05 - 1.20e-01 4.63e-06w 1\n", - " 66 0.0000000e+00 1.22e+05 1.04e+11 -1.0 7.69e+05 - 1.00e+00 2.97e-04h 9\n", - " 67 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 1.23e-01 2.96e-04h 10\n", - " 68 0.0000000e+00 1.22e+05 1.04e+11 -1.0 2.28e+05 - 5.91e-01 2.95e-04h 10\n", - " 69 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.36e-01 2.93e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.29e+05 - 1.00e+00 2.92e-04h 10\n", - " 71 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.30e+05 - 1.23e-01 2.91e-04h 10\n", - " 72 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 5.89e-01 2.90e-04h 10\n", - " 73 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.31e+05 - 1.36e-01 2.89e-04h 10\n", - " 74 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.00e+00 2.87e-04h 10\n", - " 75 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.32e+05 - 1.23e-01 2.86e-04h 10\n", - " 76 0.0000000e+00 1.74e+06 3.75e+11 -1.0 2.33e+05 - 5.86e-01 1.46e-01w 1\n", - " 77 0.0000000e+00 1.74e+06 6.57e+13 -1.0 7.62e+05 - 6.18e-02 4.58e-04w 1\n", - " 78 0.0000000e+00 1.74e+06 1.12e+17 -1.0 7.73e+05 - 2.30e-01 4.51e-06w 1\n", - " 79 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.73e+05 - 5.86e-01 2.85e-04h 9\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.36e-01 2.84e-04h 10\n", - " 81 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.34e+05 - 1.00e+00 2.83e-04h 10\n", - " 82 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 1.22e-01 2.81e-04h 10\n", - " 83 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.35e+05 - 5.83e-01 2.80e-04h 10\n", - " 84 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.36e+05 - 1.35e-01 2.79e-04h 10\n", - " 85 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.00e+00 2.78e-04h 10\n", - " 86 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.37e+05 - 1.22e-01 2.77e-04h 10\n", - " 87 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 5.81e-01 2.76e-04h 10\n", - " 88 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.38e+05 - 1.35e-01 2.74e-04h 10\n", - " 89 0.0000000e+00 1.69e+06 6.88e+11 -1.0 2.39e+05 - 1.00e+00 1.40e-01w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90 0.0000000e+00 1.69e+06 1.08e+14 -1.0 7.66e+05 - 6.03e-02 4.46e-04w 1\n", - " 91 0.0000000e+00 1.69e+06 1.14e+17 -1.0 7.77e+05 - 1.22e-01 4.40e-06w 1\n", - " 92 0.0000000e+00 1.22e+05 1.05e+11 -1.0 7.77e+05 - 1.00e+00 2.73e-04h 9\n", - " 93 0.0000000e+00 1.22e+05 1.05e+11 -1.0 2.39e+05 - 1.21e-01 2.72e-04h 10\n", - " 94 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.40e+05 - 5.78e-01 2.71e-04h 10\n", - " 95 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.34e-01 2.70e-04h 10\n", - " 96 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.41e+05 - 1.00e+00 2.69e-04h 10\n", - " 97 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 1.21e-01 2.68e-04h 10\n", - " 98 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.42e+05 - 5.76e-01 2.67e-04h 10\n", - " 99 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.43e+05 - 1.34e-01 2.65e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.00e+00 2.64e-04h 10\n", - " 101 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.44e+05 - 1.20e-01 2.63e-04h 10\n", - " 102 0.0000000e+00 1.64e+06 4.17e+11 -1.0 2.45e+05 - 5.73e-01 1.34e-01w 1\n", - " 103 0.0000000e+00 1.64e+06 7.61e+13 -1.0 7.71e+05 - 6.17e-02 4.35e-04w 1\n", - " 104 0.0000000e+00 1.64e+06 1.17e+17 -1.0 7.81e+05 - 2.38e-01 4.29e-06w 1\n", - " 105 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.81e+05 - 5.73e-01 2.62e-04h 9\n", - " 106 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.45e+05 - 1.34e-01 2.61e-04h 10\n", - " 107 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.46e+05 - 1.00e+00 2.60e-04h 10\n", - " 108 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 1.20e-01 2.59e-04h 10\n", - " 109 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.47e+05 - 5.71e-01 2.58e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.48e+05 - 1.33e-01 2.57e-04h 10\n", - " 111 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.00e+00 2.56e-04h 10\n", - " 112 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.49e+05 - 1.19e-01 2.55e-04h 10\n", - " 113 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 5.68e-01 2.54e-04h 10\n", - " 114 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.50e+05 - 1.33e-01 2.53e-04h 10\n", - " 115 0.0000000e+00 1.59e+06 7.85e+11 -1.0 2.51e+05 - 1.00e+00 1.29e-01w 1\n", - " 116 0.0000000e+00 1.59e+06 1.28e+14 -1.0 7.75e+05 - 6.01e-02 4.25e-04w 1\n", - " 117 0.0000000e+00 1.59e+06 1.19e+17 -1.0 7.85e+05 - 1.23e-01 4.19e-06w 1\n", - " 118 0.0000000e+00 1.21e+05 1.05e+11 -1.0 7.85e+05 - 1.00e+00 2.52e-04h 9\n", - " 119 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 1.19e-01 2.51e-04h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.52e+05 - 5.66e-01 2.50e-04h 10\n", - " 121 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.32e-01 2.49e-04h 10\n", - " 122 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.53e+05 - 1.00e+00 2.47e-04h 10\n", - " 123 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.54e+05 - 1.18e-01 4.93e-04h 9\n", - " 124 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.55e+05 - 5.60e-01 4.89e-04h 9\n", - " 125 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.56e+05 - 1.32e-01 4.85e-04h 9\n", - " 126 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.58e+05 - 1.00e+00 4.81e-04h 9\n", - " 127 0.0000000e+00 1.21e+05 1.05e+11 -1.0 2.59e+05 - 1.18e-01 4.77e-04h 9\n", - " 128 0.0000000e+00 1.52e+06 4.74e+11 -1.0 2.60e+05 - 5.55e-01 1.21e-01w 1\n", - " 129 0.0000000e+00 1.52e+06 9.09e+13 -1.0 7.80e+05 - 6.17e-02 4.09e-04w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130 0.0000000e+00 1.52e+06 1.22e+17 -1.0 7.90e+05 - 2.48e-01 4.04e-06w 1\n", - " 131 0.0000000e+00 1.20e+05 1.05e+11 -1.0 7.90e+05 - 5.55e-01 4.73e-04h 8\n", - " 132 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.61e+05 - 1.31e-01 4.69e-04h 9\n", - " 133 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.63e+05 - 1.00e+00 1.86e-03h 7\n", - " 134 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.67e+05 - 1.16e-01 1.80e-03h 7\n", - " 135 0.0000000e+00 1.20e+05 1.05e+11 -1.0 2.72e+05 - 5.16e-01 1.74e-03h 7\n", - " 136 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.77e+05 - 1.29e-01 3.38e-03h 6\n", - " 137 0.0000000e+00 1.19e+05 1.05e+11 -1.0 2.87e+05 - 1.00e+00 3.17e-03h 6\n", - " 138 0.0000000e+00 1.19e+05 1.06e+11 -1.0 2.98e+05 - 1.10e-01 2.97e-03h 6\n", - " 139 0.0000000e+00 1.18e+05 1.06e+11 -1.0 3.08e+05 - 4.88e-01 2.79e-03h 6\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140 0.0000000e+00 1.18e+05 1.07e+11 -1.0 3.18e+05 - 1.22e-01 5.25e-03h 5\n", - " 141 0.0000000e+00 1.01e+06 1.89e+12 -1.0 3.38e+05 - 1.00e+00 7.42e-02w 1\n", - " 142 0.0000000e+00 1.01e+06 3.99e+14 -1.0 8.16e+05 - 5.93e-02 3.07e-04w 1\n", - " 143 0.0000000e+00 1.01e+06 1.56e+17 -1.0 8.24e+05 - 1.44e-01 3.04e-06w 1\n", - " 144 0.0000000e+00 1.17e+05 1.08e+11 -1.0 8.24e+05 - 1.00e+00 4.64e-03h 4\n", - " 145 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.59e+05 - 1.01e-01 2.06e-03h 6\n", - " 146 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.69e+05 - 4.67e-01 1.94e-03h 6\n", - " 147 0.0000000e+00 1.17e+05 1.08e+11 -1.0 3.79e+05 - 1.12e-01 1.83e-03h 6\n", - " 148 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.89e+05 - 1.00e+00 8.66e-04h 7\n", - " 149 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.94e+05 - 9.61e-02 8.42e-04h 7\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150 0.0000000e+00 1.16e+05 1.09e+11 -1.0 3.99e+05 - 4.61e-01 4.10e-04h 8\n", - " 151 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.01e+05 - 1.09e-01 4.04e-04h 8\n", - " 152 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.04e+05 - 1.00e+00 3.98e-04h 8\n", - " 153 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.06e+05 - 9.46e-02 9.83e-05h 10\n", - " 154 0.0000000e+00 6.92e+05 1.57e+12 -1.0 4.07e+05 - 4.54e-01 5.01e-02w 1\n", - " 155 0.0000000e+00 6.92e+05 4.69e+14 -1.0 8.35e+05 - 6.23e-02 2.42e-04w 1\n", - " 156 0.0000000e+00 6.92e+05 1.93e+17 -1.0 8.42e+05 - 2.97e-01 2.40e-06w 1\n", - " 157 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.42e+05 - 4.54e-01 9.79e-05h 9\n", - " 158 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.09e-01 9.76e-05h 10\n", - " 159 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.08e+05 - 1.00e+00 9.73e-05h 10\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 9.43e-02 9.70e-05h 10\n", - " 161 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.09e+05 - 4.54e-01 4.83e-05h 11\n", - " 162 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.08e-01 4.82e-05h 11\n", - " 163 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 1.00e+00 1.20e-05h 13\n", - " 164 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 9.42e-02 1.20e-05h 13\n", - " 165 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.10e+05 - 4.55e-01 9.62e-05h 10\n", - " 166 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.11e+05 - 1.08e-01 9.59e-05h 10\n", - " 167 0.0000000e+00 6.75e+05 3.70e+12 -1.0 4.11e+05 - 1.00e+00 4.89e-02w 1\n", - " 168 0.0000000e+00 6.74e+05 9.73e+14 -1.0 8.36e+05 - 5.90e-02 2.39e-04w 1\n", - " 169 0.0000000e+00 6.74e+05 1.96e+17 -1.0 8.43e+05 - 1.50e-01 2.37e-06w 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170 0.0000000e+00 1.16e+05 1.09e+11 -1.0 8.43e+05 - 1.00e+00 9.56e-05h 9\n", - " 171 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 9.39e-02 2.38e-05h 12\n", - " 172 0.0000000e+00 1.16e+05 1.09e+11 -1.0 4.12e+05 - 4.52e-01 1.19e-05h 13\n", - " 173r 0.0000000e+00 1.16e+05 1.00e+03 0.6 0.00e+00 - 0.00e+00 3.72e-07R 18\n", - " 174r 0.0000000e+00 1.25e+05 1.78e+03 0.6 3.70e+04 - 1.19e-02 1.34e-03f 1\n", - " 175r 0.0000000e+00 1.10e+05 1.54e+03 0.6 7.30e+03 - 3.61e-03 8.33e-03f 1\n", - " 176r 0.0000000e+00 1.02e+05 4.12e+03 0.6 5.25e+03 - 6.33e-02 8.82e-03f 1\n", - " 177r 0.0000000e+00 9.63e+04 4.43e+03 0.6 4.50e+03 - 3.61e-02 2.36e-02f 1\n", - " 178r 0.0000000e+00 9.20e+04 1.63e+04 0.6 3.97e+03 - 2.78e-01 6.99e-02f 1\n", - " 179r 0.0000000e+00 8.79e+04 3.34e+04 0.6 4.66e+02 - 8.68e-01 3.38e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.06e+05 3.33e+02 0.6 1.05e+02 - 1.00e+00 1.00e+00f 1\n", - " 181r 0.0000000e+00 1.05e+05 2.26e+02 0.6 2.72e+01 - 1.00e+00 1.00e+00f 1\n", - " 182r 0.0000000e+00 9.53e+04 2.03e+03 -0.1 2.12e+02 - 1.00e+00 7.99e-01f 1\n", - " 183r 0.0000000e+00 8.64e+04 8.95e+01 -0.1 8.37e+01 - 1.00e+00 1.00e+00f 1\n", - " 184r 0.0000000e+00 8.52e+04 9.30e-01 -0.1 4.13e+01 - 1.00e+00 1.00e+00h 1\n", - " 185r 0.0000000e+00 7.70e+04 7.43e+02 -2.2 2.70e+02 - 8.39e-01 7.19e-01f 1\n", - " 186r 0.0000000e+00 7.27e+04 1.42e+03 -2.2 1.95e+03 - 9.32e-01 6.47e-01f 1\n", - " 187r 0.0000000e+00 7.36e+04 5.69e+02 -2.2 4.90e+02 - 9.15e-01 6.73e-01f 1\n", - " 188r 0.0000000e+00 7.91e+04 2.05e+02 -2.2 2.75e+02 - 1.00e+00 8.69e-01f 1\n", - " 189r 0.0000000e+00 7.92e+04 1.27e+03 -2.2 1.37e+02 - 8.68e-01 1.06e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 7.99e+04 8.09e+01 -2.2 1.45e+02 - 1.00e+00 1.00e+00f 1\n", - " 191r 0.0000000e+00 8.00e+04 1.81e+01 -2.2 2.82e+00 - 1.00e+00 1.00e+00f 1\n", - " 192r 0.0000000e+00 8.00e+04 6.93e-02 -2.2 6.43e-02 - 1.00e+00 1.00e+00h 1\n", - " 193r 0.0000000e+00 8.03e+04 1.79e+02 -3.3 1.75e+01 - 9.50e-01 8.57e-01f 1\n", - " 194r 0.0000000e+00 4.29e+04 3.40e+02 -3.3 8.69e+02 - 1.00e+00 6.02e-01f 1\n", - " 195r 0.0000000e+00 1.36e+04 1.76e+01 -3.3 3.71e+02 - 1.00e+00 1.00e+00f 1\n", - " 196r 0.0000000e+00 1.99e+04 5.38e-01 -3.3 7.89e+01 - 1.00e+00 1.00e+00h 1\n", - " 197r 0.0000000e+00 1.73e+04 9.03e-02 -3.3 3.20e+01 - 1.00e+00 1.00e+00h 1\n", - " 198r 0.0000000e+00 1.64e+04 1.32e-02 -3.3 1.07e+01 - 1.00e+00 1.00e+00h 1\n", - " 199r 0.0000000e+00 1.48e+04 9.83e+01 -4.9 2.40e+01 - 8.62e-01 7.80e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 1.44e+04 1.92e+03 -4.9 1.71e+03 - 6.01e-01 1.17e-02f 1\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", + " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", + " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", + " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", + " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", + " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", + " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 200\n", + "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 8.8349814638582666e+02 8.8349814638582666e+02\n", - "Constraint violation....: 3.3086142754792485e-04 1.4369018418593043e+04\n", - "Complementarity.........: 6.5630241357471754e-04 6.5630241357471754e-04\n", - "Overall NLP error.......: 3.3086142754792485e-04 1.4369018418593043e+04\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", "\n", "\n", - "Number of objective function evaluations = 1605\n", - "Number of objective gradient evaluations = 175\n", - "Number of equality constraint evaluations = 1605\n", + "Number of objective function evaluations = 12\n", + "Number of objective gradient evaluations = 10\n", + "Number of equality constraint evaluations = 12\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 202\n", + "Number of equality constraint Jacobian evaluations = 10\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 200\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.331\n", - "Total CPU secs in NLP function evaluations = 0.025\n", + "Number of Lagrangian Hessian evaluations = 9\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", + "Total CPU secs in NLP function evaluations = 0.000\n", "\n", - "EXIT: Maximum Number of Iterations Exceeded.\n", - "WARNING: Loading a SolverResults object with a warning status into\n", - "model.name=\"unknown\";\n", - " - termination condition: maxIterations\n", - " - message from solver: Ipopt 3.13.2\\x3a Maximum Number of Iterations\n", - " Exceeded.\n" + "EXIT: Optimal Solution Found.\n" ] } ], "execution_count": 52 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.967629Z", - "start_time": "2025-06-11T22:13:31.943574Z" + "end_time": "2025-06-24T19:31:57.464844Z", + "start_time": "2025-06-24T19:31:57.440973Z" } }, - "cell_type": "code", "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1921,30 +1738,34 @@ "execution_count": 53 }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6 Solving the Model" + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, - "source": "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:31.982093Z", - "start_time": "2025-06-11T22:13:31.978929Z" + "end_time": "2025-06-24T19:31:57.483016Z", + "start_time": "2025-06-24T19:31:57.480415Z" } }, - "cell_type": "code", "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 500,\n", + " \"max_iter\": 1000,\n", " \"tol\": 1e-8,\n", "}" ], @@ -1952,12 +1773,12 @@ "execution_count": 54 }, { + "cell_type": "markdown", "metadata": { "tags": [ "exercise" ] }, - "cell_type": "markdown", "source": [ "
\n", "Inline Exercise:\n", @@ -1977,8 +1798,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.012062Z", - "start_time": "2025-06-11T22:13:32.008341Z" + "end_time": "2025-06-24T19:31:57.510879Z", + "start_time": "2025-06-24T19:31:57.508276Z" } }, "source": [ @@ -1996,8 +1817,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:32.320588Z", - "start_time": "2025-06-11T22:13:32.041379Z" + "end_time": "2025-06-24T19:31:58.312733Z", + "start_time": "2025-06-24T19:31:57.533935Z" } }, "source": [ @@ -2016,10 +1837,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1n1inahr_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2057,116 +1878,298 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 7.98e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.94e+04 1.91e+01 -1.0 1.01e+05 - 4.59e-03 3.67e-03h 3\n", - " 2 0.0000000e+00 7.91e+04 2.90e+01 -1.0 9.74e+04 - 1.04e-02 2.90e-03h 3\n", - " 3 0.0000000e+00 8.53e+04 3.58e+01 -1.0 1.09e+05 - 3.03e-02 2.27e-03h 3\n", - " 4 0.0000000e+00 9.38e+04 9.70e+01 -1.0 1.22e+05 - 2.53e-02 1.76e-03h 3\n", - " 5 0.0000000e+00 9.86e+04 7.07e+02 -1.0 1.32e+05 - 5.90e-02 1.36e-03h 3\n", - " 6 0.0000000e+00 1.01e+05 5.02e+03 -1.0 1.41e+05 - 2.55e-02 1.04e-03h 3\n", - " 7 0.0000000e+00 1.03e+05 1.80e+05 -1.0 1.47e+05 - 1.27e-01 7.95e-04h 3\n", - " 8 0.0000000e+00 1.04e+05 2.00e+06 -1.0 1.52e+05 - 2.40e-02 6.05e-04h 3\n", - " 9 0.0000000e+00 1.04e+05 1.82e+08 -1.0 1.56e+05 - 1.71e-01 4.59e-04h 3\n", + " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", + " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", + " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", + " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", + " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", + " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", + " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", + " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", + " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", + " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", + " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", + " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", + " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", + " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", + " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", + " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", + " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", + " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", + " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", + " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", + " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", + " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", + " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", + " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", + " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", + " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", + " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", + " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", + " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", + " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", + " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", + " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", + " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", + " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", + " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", + " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", + " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", + " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", + " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 0.0000000e+00 1.04e+05 3.34e+09 -1.0 1.59e+05 - 2.46e-02 3.47e-04h 3\n", - " 11 0.0000000e+00 3.24e+05 3.06e+09 -1.0 2.71e-02 10.0 5.85e-01 7.83e-01h 1\n", - " 12 0.0000000e+00 1.46e+06 3.17e+11 -1.0 3.46e+04 - 7.72e-02 1.50e-01f 2\n", - " 13 0.0000000e+00 1.46e+06 2.27e+11 -1.0 1.90e+04 - 3.66e-01 2.41e-03h 3\n", - " 14 0.0000000e+00 1.46e+06 2.32e+12 -1.0 1.90e+04 - 4.42e-01 1.83e-03h 3\n", - " 15 0.0000000e+00 1.45e+06 8.61e+13 -1.0 1.89e+04 - 4.59e-01 1.39e-03h 3\n", - " 16 0.0000000e+00 1.45e+06 5.60e+14 -1.0 1.89e+04 - 3.52e-01 2.10e-03h 2\n", - " 17 0.0000000e+00 1.45e+06 5.54e+14 -1.0 1.88e+04 - 5.07e-01 1.07e-03h 2\n", - " 18 0.0000000e+00 1.45e+06 9.90e+14 -1.0 1.88e+04 - 3.35e-01 1.09e-03h 1\n", - " 19 0.0000000e+00 1.45e+06 9.94e+16 -1.0 1.87e+04 - 9.49e-01 1.09e-05h 1\n", + " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", + " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", + " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", + " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", + " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", + " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", + " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 0.0000000e+00 1.44e+06 9.35e+18 -1.0 4.45e+03 - 2.73e-01 2.89e-03h 1\n", - " 21r 0.0000000e+00 1.44e+06 1.00e+03 -0.6 0.00e+00 - 0.00e+00 4.43e-07R 17\n", - " 22r 0.0000000e+00 1.89e+06 2.04e+03 -0.6 6.64e+02 - 7.96e-03 2.69e-03f 1\n", - " 23r 0.0000000e+00 1.93e+06 4.07e+03 -0.6 8.47e+02 - 1.23e-02 4.48e-03f 1\n", - " 24r 0.0000000e+00 2.28e+06 1.29e+04 -0.6 9.49e+02 - 4.42e-02 1.55e-02f 1\n", - " 25r 0.0000000e+00 4.06e+06 1.16e+04 -0.6 1.05e+03 - 5.19e-02 5.05e-02f 1\n", - " 26r 0.0000000e+00 4.03e+06 6.56e+03 -0.6 8.19e+02 - 2.50e-03 1.07e-02f 1\n", - " 27r 0.0000000e+00 4.15e+06 4.04e+04 -0.6 6.67e+02 - 9.08e-02 3.63e-02f 1\n", - " 28r 0.0000000e+00 4.11e+06 4.55e+04 -0.6 4.90e+02 - 4.20e-02 3.20e-02f 1\n", - " 29r 0.0000000e+00 4.02e+06 1.82e+05 -0.6 4.75e+02 - 2.06e-01 1.68e-02f 1\n", + " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", + " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", + " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", + " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", + " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", + " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", + " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", + " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", + " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.02e+06 8.10e+04 -0.6 4.67e+02 - 6.59e-02 2.37e-01f 1\n", - " 31r 0.0000000e+00 2.70e+06 1.53e+05 -0.6 3.56e+02 - 4.76e-01 4.13e-01f 1\n", - " 32r 0.0000000e+00 2.13e+06 9.21e+04 -0.6 2.09e+02 - 4.07e-01 5.13e-01f 1\n", - " 33r 0.0000000e+00 8.87e+05 5.96e+04 -0.6 1.02e+02 - 5.00e-01 5.95e-01f 1\n", - " 34r 0.0000000e+00 1.36e+05 9.02e+04 -0.6 4.12e+01 - 4.56e-01 1.00e+00f 1\n", - " 35r 0.0000000e+00 4.01e+04 7.97e+04 -0.6 4.66e+00 - 5.29e-01 7.78e-01f 1\n", - " 36r 0.0000000e+00 2.04e+04 5.00e+04 -0.6 4.15e-01 0.0 3.36e-01 7.33e-01h 1\n", - " 37r 0.0000000e+00 1.98e+04 1.42e+04 -0.6 8.68e-02 1.3 1.00e+00 1.72e-01f 1\n", - " 38r 0.0000000e+00 1.85e+04 2.28e+04 -0.6 1.70e+01 - 8.27e-01 5.31e-01f 1\n", - " 39r 0.0000000e+00 2.67e+04 6.30e+03 -0.6 1.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", + " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", + " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", + " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", + " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", + " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", + " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 1.76e+04 3.54e+02 -0.6 3.83e+00 - 1.00e+00 1.00e+00f 1\n", - " 41r 0.0000000e+00 1.66e+04 6.18e+02 -0.6 2.10e+00 - 1.00e+00 1.00e+00f 1\n", - " 42r 0.0000000e+00 1.63e+04 1.63e+00 -0.6 7.37e-02 - 1.00e+00 1.00e+00h 1\n", - " 43r 0.0000000e+00 1.82e+04 9.49e+02 -2.0 8.67e+00 - 8.62e-01 7.60e-01f 1\n", - " 44r 0.0000000e+00 2.02e+04 6.57e+02 -2.0 2.22e+03 - 1.00e+00 7.24e-01f 1\n", - " 45r 0.0000000e+00 1.41e+04 2.64e+01 -2.0 1.93e-02 0.9 1.00e+00 1.00e+00f 1\n", - " 46r 0.0000000e+00 1.41e+04 3.99e+00 -2.0 1.76e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 47r 0.0000000e+00 1.41e+04 5.62e-02 -2.0 3.33e-02 -0.1 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 1.42e+04 3.60e+02 -4.4 9.99e-02 -0.6 9.21e-01 7.93e-01f 1\n", - " 49r 0.0000000e+00 4.27e+04 2.99e+03 -4.4 1.29e+00 -1.1 8.82e-01 6.65e-01f 1\n", + " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", + " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", + " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", + " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", + " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", + " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", + " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 6.63e+04 1.41e+02 -4.4 3.88e+00 -1.5 9.39e-01 9.16e-01f 1\n", - " 51r 0.0000000e+00 5.62e+04 5.64e+02 -4.4 1.16e+01 -2.0 1.00e+00 1.56e-01f 1\n", - " 52r 0.0000000e+00 5.59e+04 9.07e+02 -4.4 4.50e+04 - 7.98e-02 5.51e-03f 1\n", - " 53r 0.0000000e+00 5.59e+04 1.82e+03 -4.4 2.65e+03 - 1.77e-01 2.25e-05f 1\n", - " 54r 0.0000000e+00 4.87e+04 1.59e+03 -4.4 2.65e+03 - 1.12e-01 1.38e-01f 1\n", - " 55r 0.0000000e+00 4.71e+04 2.05e+03 -4.4 2.28e+03 - 5.83e-01 3.36e-02f 1\n", - " 56r 0.0000000e+00 4.59e+04 2.00e+03 -4.4 2.21e+03 - 2.61e-02 2.52e-02f 1\n", - " 57r 0.0000000e+00 4.21e+04 1.20e+03 -4.4 2.15e+03 - 3.82e-01 9.47e-02f 1\n", - " 58r 0.0000000e+00 3.52e+04 1.00e+03 -4.4 1.95e+03 - 1.89e-01 5.87e-01f 1\n", - " 59r 0.0000000e+00 1.42e+04 3.94e+00 -4.4 8.05e+02 - 1.00e+00 1.00e+00f 1\n", + " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", + " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", + " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", + " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", + " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", + " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", + " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", + " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.42e+04 4.68e-01 -4.4 5.35e-01 - 1.00e+00 1.00e+00h 1\n", - " 61r 0.0000000e+00 1.42e+04 1.29e-02 -4.4 3.24e-03 - 1.00e+00 1.00e+00h 1\n", - " 62r 0.0000000e+00 1.42e+04 5.72e-06 -4.4 5.73e-05 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 1.42e+04 1.24e+02 -6.6 2.71e-01 - 9.90e-01 8.10e-01f 1\n", - " 64r 0.0000000e+00 8.72e+05 1.88e+02 -6.6 3.29e+04 - 5.03e-01 2.23e-01f 1\n", - " 65r 0.0000000e+00 1.05e+06 2.88e+02 -6.6 2.53e+04 - 6.78e-01 1.82e-01f 1\n", - " 66r 0.0000000e+00 1.04e+06 4.92e+02 -6.6 8.71e+03 - 8.61e-01 1.13e-02f 1\n", - " 67r 0.0000000e+00 6.27e+05 7.17e+01 -6.6 8.61e+03 - 1.00e+00 8.73e-01f 1\n", - " 68r 0.0000000e+00 2.18e+04 1.48e+00 -6.6 1.09e+03 - 1.00e+00 1.00e+00h 1\n", - " 69r 0.0000000e+00 4.71e+02 5.81e-05 -6.6 7.59e-02 - 1.00e+00 1.00e+00h 1\n", + " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", + " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", + " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", + " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", + " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", + " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", + " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", + " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", + " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", + " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 4.71e+02 1.03e-08 -6.6 1.22e-05 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 4.71e+02 8.08e-01 -9.0 4.39e-02 - 1.00e+00 9.74e-01f 1\n", - " 72r 0.0000000e+00 2.45e+03 1.39e+02 -9.0 2.20e+05 - 3.58e-01 2.17e-03f 1\n", - " 73r 0.0000000e+00 2.39e+03 5.81e+02 -9.0 1.06e+04 - 6.57e-01 2.41e-02f 1\n", - " 74r 0.0000000e+00 2.15e+04 7.82e+02 -9.0 1.04e+04 - 1.00e+00 1.42e-01f 1\n", - " 75r 0.0000000e+00 1.15e+04 4.72e+02 -9.0 4.34e+01 - 1.00e+00 4.66e-01h 2\n", - " 76r 0.0000000e+00 6.38e+03 2.52e+02 -9.0 4.28e+01 - 1.00e+00 4.46e-01h 2\n", - " 77r 0.0000000e+00 3.26e+03 1.28e+02 -9.0 2.42e+01 - 1.00e+00 4.89e-01h 2\n", - " 78r 0.0000000e+00 2.99e+03 1.10e+02 -9.0 1.24e+01 - 1.00e+00 1.00e+00h 1\n", - " 79r 0.0000000e+00 9.57e+01 3.79e+00 -9.0 5.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", + " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", + " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", + " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", + " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", + " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", + " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", + " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", + " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 3.70e-02 1.01e-04 -9.0 3.14e-05 - 1.00e+00 1.00e+00h 1\n", - " 81r 0.0000000e+00 4.15e-06 2.24e-09 -9.0 8.12e-09 - 1.00e+00 1.00e+00h 1\n", + " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", + " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", + " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", + " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", + " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", + " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", + " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", + " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", + " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", + " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", + " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", + " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", + " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", + " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", + " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", + " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", + " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", + " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", + " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", + " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", + " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", + " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", + " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", + " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", + " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", + " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", + " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", + " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", + " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", + " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", + " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", + " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", + " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", + " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", + " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", + " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", + " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", + " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", + " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", + " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", + " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", + " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", + " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", + " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", + " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", + " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", + " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", + " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", + " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", + " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", + " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", + " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", + " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", + " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", + " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", + " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", + " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", + " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", + " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", + " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", + " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", + " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", + " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", + " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", + " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", + " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", + " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", + " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", + " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", + " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", + " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", + " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", + " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", + " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", + " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", + " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", + " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", + " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", + " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", + " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", + " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", + " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", + " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", + " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", + " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", + " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", + " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", + " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", + " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", + " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", + " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", + " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", + " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", + " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", + " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", + " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", + " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", + " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", + " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", + " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", + " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", + " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", + " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", + " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", + " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", + " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", + " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 81\n", + "Number of Iterations....: 247\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 4.1499733924865723e-06\n", + "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", "\n", "\n", - "Number of objective function evaluations = 162\n", - "Number of objective gradient evaluations = 23\n", - "Number of equality constraint evaluations = 162\n", + "Number of objective function evaluations = 506\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 507\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 83\n", + "Number of equality constraint Jacobian evaluations = 250\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 81\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.119\n", - "Total CPU secs in NLP function evaluations = 0.006\n", + "Number of Lagrangian Hessian evaluations = 247\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", + "Total CPU secs in NLP function evaluations = 0.031\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2184,62 +2187,47 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] }, { + "cell_type": "code", "metadata": { "tags": [ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.874186Z", - "start_time": "2025-06-11T22:13:32.362868Z" + "end_time": "2025-06-24T19:31:58.337367Z", + "start_time": "2025-06-24T19:31:58.332051Z" } }, - "cell_type": "code", "source": [ - "m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Started visualization server\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Loading saved flowsheet from 'HDA-Flowsheet.json'\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Saving flowsheet to default file 'HDA-Flowsheet.json' in current directory (C:\\Users\\Tanner\\Documents\\git\\examples\\idaes_examples\\notebooks\\docs\\tut\\core)\n", - "2025-06-11 16:13:33 [INFO] idaes.idaes_ui.fv.fsvis: Flowsheet visualization at: http://localhost:49167/app?id=HDA-Flowsheet\n" - ] - }, - { - "data": { - "text/plain": [ - "VisualizeResult(store=, port=49167, server=, save_diagram=>)" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } + "# m.fs.visualize(\"HDA-Flowsheet\")" ], + "outputs": [], "execution_count": 58 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] }, { + "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:33.985892Z", - "start_time": "2025-06-11T22:13:33.889113Z" + "end_time": "2025-06-24T19:31:58.418255Z", + "start_time": "2025-06-24T19:31:58.357169Z" } }, - "cell_type": "code", - "source": "m.fs.report()", + "source": [ + "m.fs.report()" + ], "outputs": [ { "name": "stdout", @@ -2251,8 +2239,8 @@ "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2993e-07 1.2993e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4149e-07 8.4149e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2268,16 +2256,18 @@ "execution_count": 59 }, { - "metadata": {}, "cell_type": "markdown", - "source": "What is the total operating cost?" + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.015352Z", - "start_time": "2025-06-11T22:13:34.012518Z" + "end_time": "2025-06-24T19:31:58.432469Z", + "start_time": "2025-06-24T19:31:58.429050Z" } }, "source": [ @@ -2288,7 +2278,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33874473866\n" + "operating cost = $ 419122.33873277955\n" ] } ], @@ -2297,14 +2287,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.197557Z", - "start_time": "2025-06-11T22:13:34.174732Z" + "end_time": "2025-06-24T19:31:58.563246Z", + "start_time": "2025-06-24T19:31:58.542913Z" } }, "source": [ @@ -2345,7 +2337,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242962943922332\n" + "benzene purity = 0.824296294393142\n" ] } ], @@ -2354,14 +2346,16 @@ { "cell_type": "markdown", "metadata": {}, - "source": "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.253529Z", - "start_time": "2025-06-11T22:13:34.238100Z" + "end_time": "2025-06-24T19:31:58.605718Z", + "start_time": "2025-06-24T19:31:58.589778Z" } }, "source": [ @@ -2379,8 +2373,8 @@ "output_type": "stream", "text": [ " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2993e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4149e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2427,8 +2421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.276719Z", - "start_time": "2025-06-11T22:13:34.271416Z" + "end_time": "2025-06-24T19:31:58.632091Z", + "start_time": "2025-06-24T19:31:58.629265Z" } }, "source": [ @@ -2448,8 +2442,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.337438Z", - "start_time": "2025-06-11T22:13:34.332415Z" + "end_time": "2025-06-24T19:31:58.663762Z", + "start_time": "2025-06-24T19:31:58.659017Z" } }, "source": [ @@ -2485,8 +2479,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.399247Z", - "start_time": "2025-06-11T22:13:34.395221Z" + "end_time": "2025-06-24T19:31:58.692331Z", + "start_time": "2025-06-24T19:31:58.689328Z" } }, "source": [ @@ -2502,8 +2496,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.463653Z", - "start_time": "2025-06-11T22:13:34.459960Z" + "end_time": "2025-06-24T19:31:58.721740Z", + "start_time": "2025-06-24T19:31:58.718213Z" } }, "source": [ @@ -2532,8 +2526,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.589902Z", - "start_time": "2025-06-11T22:13:34.585528Z" + "end_time": "2025-06-24T19:31:58.775901Z", + "start_time": "2025-06-24T19:31:58.772587Z" } }, "source": [ @@ -2566,8 +2560,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.678092Z", - "start_time": "2025-06-11T22:13:34.673513Z" + "end_time": "2025-06-24T19:31:58.811295Z", + "start_time": "2025-06-24T19:31:58.808287Z" } }, "source": [ @@ -2583,8 +2577,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.713177Z", - "start_time": "2025-06-11T22:13:34.709843Z" + "end_time": "2025-06-24T19:31:58.829624Z", + "start_time": "2025-06-24T19:31:58.825571Z" } }, "source": [ @@ -2606,8 +2600,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.763569Z", - "start_time": "2025-06-11T22:13:34.759916Z" + "end_time": "2025-06-24T19:31:58.844289Z", + "start_time": "2025-06-24T19:31:58.839950Z" } }, "source": [ @@ -2632,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.806470Z", - "start_time": "2025-06-11T22:13:34.801455Z" + "end_time": "2025-06-24T19:31:58.868128Z", + "start_time": "2025-06-24T19:31:58.863842Z" } }, "source": [ @@ -2668,8 +2662,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.837136Z", - "start_time": "2025-06-11T22:13:34.832491Z" + "end_time": "2025-06-24T19:31:58.891396Z", + "start_time": "2025-06-24T19:31:58.888249Z" } }, "source": [ @@ -2685,8 +2679,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.887385Z", - "start_time": "2025-06-11T22:13:34.882862Z" + "end_time": "2025-06-24T19:31:58.919132Z", + "start_time": "2025-06-24T19:31:58.916298Z" } }, "source": [ @@ -2709,8 +2703,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:34.917217Z", - "start_time": "2025-06-11T22:13:34.912683Z" + "end_time": "2025-06-24T19:31:59.013818Z", + "start_time": "2025-06-24T19:31:58.944881Z" } }, "source": [ @@ -2733,8 +2727,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.209235Z", - "start_time": "2025-06-11T22:13:34.962108Z" + "end_time": "2025-06-24T19:31:59.200536Z", + "start_time": "2025-06-24T19:31:59.023996Z" } }, "source": [ @@ -2749,10 +2743,10 @@ "component keys that are not exported as part of the NL file. Skipping.\n", "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", - "max_iter=500\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\n", + "max_iter=1000\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpd6aww4bg_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2806,67 +2800,73 @@ " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15r 3.0399961e+05 1.21e+06 1.00e+03 -0.5 0.00e+00 - 0.00e+00 3.97e-07R 14\n", - " 16r 3.0399912e+05 1.20e+06 2.84e+04 -0.5 8.47e+03 - 4.43e-03 2.34e-03f 1\n", - " 17 3.0399884e+05 1.20e+06 5.51e+05 -1.0 2.92e+04 - 2.81e-01 2.34e-06f 2\n", - " 18 3.0402874e+05 1.19e+06 4.77e+07 -1.0 2.52e+04 - 9.90e-01 4.64e-03h 1\n", - " 19 3.0402891e+05 1.19e+06 3.49e+10 -1.0 2.51e+04 - 1.00e+00 2.64e-05h 2\n", + " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", + " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", + " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", + " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", + " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 3.0402891e+05 1.19e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 3.08e-07R 8\n", - " 21r 3.0403760e+05 1.15e+06 2.58e+04 -0.8 3.66e+03 - 5.75e-03 3.60e-03f 1\n", - " 22r 3.0404498e+05 1.08e+06 3.87e+04 -0.8 3.65e+03 - 7.70e-03 6.44e-03f 1\n", - " 23r 3.0405749e+05 9.30e+05 4.54e+04 -0.8 3.63e+03 - 1.80e-02 1.60e-02f 1\n", - " 24r 3.0406463e+05 7.06e+05 4.01e+04 -0.8 3.57e+03 - 5.64e-02 3.23e-02f 1\n", - " 25r 3.0405635e+05 4.00e+05 4.80e+04 -0.8 3.45e+03 - 1.05e-01 8.20e-02f 1\n", - " 26r 3.0403684e+05 2.04e+05 2.80e+04 -0.8 3.17e+03 - 3.66e-01 1.49e-01f 1\n", - " 27r 3.0401302e+05 2.95e+04 2.21e+04 -0.8 2.70e+03 - 1.94e-01 6.28e-01f 1\n", - " 28 3.0386768e+05 2.95e+04 1.26e+02 -1.0 3.39e+06 - 4.53e-04 3.54e-06f 1\n", - " 29 3.0384876e+05 2.95e+04 8.45e+03 -1.0 1.90e+05 - 3.01e-02 3.65e-04f 1\n", + " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + "WARNING: Problem in step computation; switching to emergency mode.\n", + " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", + " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", + " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", + " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", + " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", + " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", + " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", + " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.0412267e+05 2.86e+04 2.69e+05 -1.0 2.35e+04 - 9.90e-01 3.11e-02h 1\n", - " 31 3.0843430e+05 5.11e+05 1.73e+05 -1.0 2.16e+04 - 1.00e+00 4.99e-01h 1\n", - " 32 3.1273887e+05 6.10e+05 5.58e+08 -1.0 1.09e+04 - 1.00e+00 9.90e-01h 1\n", - " 33 3.1276263e+05 3.11e+05 1.78e+08 -1.0 1.01e+03 - 1.00e+00 4.97e-01h 2\n", - " 34 3.1278673e+05 7.74e+02 1.15e+08 -1.0 6.27e+02 - 1.00e+00 9.97e-01H 1\n", - " 35 3.1278674e+05 6.28e+02 5.45e+04 -1.0 1.81e+02 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278674e+05 8.80e-03 2.62e+00 -1.0 7.71e-01 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 38 3.1278634e+05 3.73e-08 6.73e-02 -5.7 2.20e-04 - 1.00e+00 1.00e+00f 1\n", - " 39 3.1278634e+05 2.24e-08 4.40e-05 -5.7 8.48e-04 - 1.00e+00 1.00e+00h 1\n", + " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", + " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", + " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", + " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", + " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", + " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", + " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", + " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", + " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", + " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278634e+05 6.71e-08 6.16e-05 -8.6 1.75e-03 - 1.00e+00 1.00e+00h 1\n", - " 41 3.1278634e+05 3.73e-08 4.40e-05 -9.0 8.38e-04 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278634e+05 5.96e-08 4.40e-05 -9.0 1.47e-03 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 1.49e-08 4.40e-05 -9.0 5.14e-08 - 1.00e+00 1.00e+00h 1\n", - " 44 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.39e-11 - 1.00e+00 2.44e-04h 13\n", - " 45 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.89e-11 - 1.00e+00 5.00e-01h 2\n", - " 46 3.1278634e+05 1.49e-08 4.40e-05 -9.0 7.02e-11 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 6.71e-11 - 1.00e+00 5.00e-01h 2\n", - " 48 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.67e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 2.98e-08 4.40e-05 -9.0 5.52e-11 - 1.00e+00 5.00e-01h 2\n", + " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", + " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", + " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", + " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", + " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", + " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", + " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", + " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", + "Scaling factors are invalid - setting them all to 1.\n", + "MA27BD returned iflag=-4 and requires more memory.\n", + " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.16e-11 - 1.00e+00 5.00e-01h 2\n", - " 51 3.1278634e+05 2.98e-08 4.40e-05 -9.0 3.65e-11 - 1.00e+00 1.25e-01h 4\n", + " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", + " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", + " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", + " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", "\n", - "Number of Iterations....: 51\n", + "Number of Iterations....: 53\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066673e+05 3.1278633834066673e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 6.3035118071624454e-05\n", + "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", + "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622074e-10 9.2191617461622074e-10\n", - "Overall NLP error.......: 1.6340396115140405e-08 6.3035118071624454e-05\n", + "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", + "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", "\n", "\n", - "Number of objective function evaluations = 141\n", + "Number of objective function evaluations = 105\n", "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 141\n", - "Number of inequality constraint evaluations = 141\n", - "Number of equality constraint Jacobian evaluations = 55\n", - "Number of inequality constraint Jacobian evaluations = 55\n", - "Number of Lagrangian Hessian evaluations = 52\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.077\n", - "Total CPU secs in NLP function evaluations = 0.010\n", + "Number of equality constraint evaluations = 105\n", + "Number of inequality constraint evaluations = 105\n", + "Number of equality constraint Jacobian evaluations = 56\n", + "Number of inequality constraint Jacobian evaluations = 56\n", + "Number of Lagrangian Hessian evaluations = 54\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", + "Total CPU secs in NLP function evaluations = 0.004\n", "\n", "EXIT: Solved To Acceptable Level.\n" ] @@ -2887,8 +2887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.321235Z", - "start_time": "2025-06-11T22:13:35.245545Z" + "end_time": "2025-06-24T19:31:59.272458Z", + "start_time": "2025-06-24T19:31:59.235423Z" } }, "source": [ @@ -2911,7 +2911,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.33834066667\n", + "operating cost = $ 312786.3383406669\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2941,7 +2941,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115882\n", + "benzene purity = 0.8188276578115892\n", "\n", "Overhead loss in F101\n", "\n", @@ -2986,8 +2986,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-11T22:13:35.405538Z", - "start_time": "2025-06-11T22:13:35.398221Z" + "end_time": "2025-06-24T19:31:59.312310Z", + "start_time": "2025-06-24T19:31:59.308432Z" } }, "source": [ @@ -3044,7 +3044,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.12.3" } }, "nbformat": 4, From b41541f344ff31a97beaba1a2926ef7847ad281a Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 26 Jun 2025 11:32:32 -0700 Subject: [PATCH 32/36] Fixed spelling and ran Black --- .../notebooks/docs/tut/core/flash_unit.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_doc.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_exercise.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_solution.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_test.ipynb | 2 +- .../notebooks/docs/tut/core/flash_unit_usr.ipynb | 2 +- .../notebooks/docs/tut/core/hda_flowsheet.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_doc.ipynb | 11 +++++------ .../docs/tut/core/hda_flowsheet_exercise.ipynb | 11 +++++------ .../docs/tut/core/hda_flowsheet_solution.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_test.ipynb | 11 +++++------ .../notebooks/docs/tut/core/hda_flowsheet_usr.ipynb | 11 +++++------ 12 files changed, 36 insertions(+), 42 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb index a44b3af3..98bea68f 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb index 07569d68..bb186921 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_doc.ipynb @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb index 81943bc9..7896bd57 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_exercise.ipynb @@ -164,7 +164,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb index bf8397d4..9cb8329c 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_solution.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb index 723382dd..d0a1de40 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_test.ipynb @@ -168,7 +168,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb index bf8397d4..9cb8329c 100644 --- a/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/flash_unit_usr.ipynb @@ -199,7 +199,7 @@ "\n", "We need to define the property package for our flowsheet. In this example, we will be using the ideal property package that is available as part of the IDAES framework. This property package supports ideal gas - ideal liquid, ideal gas - NRTL, and ideal gas - Wilson models for VLE. More details on this property package can be found at: https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/property_models/activity_coefficient.html\n", "\n", - "IDAES also supports creation of your own property packages that will be shown in a later module. More detials can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", + "IDAES also supports creation of your own property packages that will be shown in a later module. More details can be found here https://idaes-examples.readthedocs.io/en/latest/docs/properties/custom/index.html\n", "\n", "For this workshop, we will import the BTX_activity_coeff_VLE property parameter block to be used in the flowsheet. This properties block will be passed to our unit model to define the appropriate state variables and equations for performing thermodynamic calculations.\n", "\n", diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index ec841572..1657be48 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -1565,7 +1565,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1592,7 +1591,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1642,10 +1641,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 6434a3ca..4e387ef6 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1358,7 +1358,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1385,7 +1384,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1435,10 +1434,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 4b548c13..fa69aa58 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1426,7 +1426,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1453,7 +1452,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1503,10 +1502,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 1f252838..a34d330c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1529,7 +1529,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1556,7 +1555,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1606,10 +1605,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index de891a01..4ab76338 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1394,7 +1394,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1421,7 +1420,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1471,10 +1470,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 1f252838..a34d330c 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1529,7 +1529,6 @@ } }, "source": [ - "\n", "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", @@ -1556,7 +1555,7 @@ "propagate_state(\n", " m.fs.s11\n", ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n" + "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], "outputs": [ { @@ -1606,10 +1605,10 @@ }, "source": [ "optarg = {\n", - " 'nlp_scaling_method': 'user-scaling',\n", - " 'OF_ma57_automatic_scaling': 'yes',\n", - " 'max_iter': 300,\n", - " 'tol': 1e-8,\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", "}\n", "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" From d593b3ebfd3205016f7aae8c497263b823d5b84f Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 26 Jun 2025 13:28:56 -0700 Subject: [PATCH 33/36] Fixing pytesting for earlier versions --- .../docs/tut/core/hda_flowsheet.ipynb | 908 +++++++----------- .../docs/tut/core/hda_flowsheet_doc.ipynb | 828 +++++++--------- .../tut/core/hda_flowsheet_exercise.ipynb | 451 +++++---- .../tut/core/hda_flowsheet_solution.ipynb | 872 +++++++---------- .../docs/tut/core/hda_flowsheet_test.ipynb | 864 +++++++---------- .../docs/tut/core/hda_flowsheet_usr.ipynb | 872 +++++++---------- 6 files changed, 1933 insertions(+), 2862 deletions(-) diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 1657be48..58481dd5 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -882,8 +882,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.360025Z", - "start_time": "2025-06-24T19:31:55.338112Z" + "end_time": "2025-06-26T20:17:04.810084Z", + "start_time": "2025-06-26T20:17:04.786754Z" } }, "source": [ @@ -904,8 +904,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -943,8 +943,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -975,8 +975,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -996,8 +996,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1028,8 +1028,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1066,8 +1066,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1083,8 +1083,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1105,8 +1105,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1139,8 +1139,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1156,8 +1156,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1181,8 +1181,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.652507Z", - "start_time": "2025-06-24T19:31:55.628692Z" + "end_time": "2025-06-26T20:17:05.104838Z", + "start_time": "2025-06-26T20:17:05.080097Z" } }, "source": [ @@ -1199,8 +1199,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1240,8 +1240,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1269,8 +1269,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1300,8 +1300,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1340,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1377,8 +1377,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1404,8 +1404,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1428,8 +1428,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1451,8 +1451,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1480,8 +1480,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1511,8 +1511,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1525,7 +1525,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1560,8 +1560,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1598,27 +1598,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1635,8 +1635,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1659,9 +1659,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1699,25 +1699,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1747,8 +1747,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1792,8 +1792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1833,8 +1833,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1852,8 +1852,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1873,9 +1873,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1913,298 +1913,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2219,8 +2056,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.324104Z", - "start_time": "2025-06-24T19:31:58.321662Z" + "end_time": "2025-06-26T20:17:07.713878Z", + "start_time": "2025-06-26T20:17:07.711084Z" } }, "source": [ @@ -2255,8 +2092,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2276,8 +2113,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2295,7 +2132,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2321,8 +2158,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2333,7 +2170,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2346,8 +2183,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.533714Z", - "start_time": "2025-06-24T19:31:58.461636Z" + "end_time": "2025-06-26T20:17:08.014719Z", + "start_time": "2025-06-26T20:17:07.926032Z" } }, "source": [ @@ -2369,8 +2206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2411,7 +2248,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2424,8 +2261,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.576962Z", - "start_time": "2025-06-24T19:31:58.573769Z" + "end_time": "2025-06-26T20:17:08.063578Z", + "start_time": "2025-06-26T20:17:08.060157Z" } }, "source": [ @@ -2447,8 +2284,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2467,7 +2304,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2514,8 +2351,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2535,8 +2372,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2572,8 +2409,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2589,8 +2426,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2607,8 +2444,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.762582Z", - "start_time": "2025-06-24T19:31:58.737160Z" + "end_time": "2025-06-26T20:17:08.275146Z", + "start_time": "2025-06-26T20:17:08.249526Z" } }, "source": [ @@ -2636,8 +2473,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2670,8 +2507,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2687,8 +2524,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2710,8 +2547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2736,8 +2573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2772,8 +2609,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2789,8 +2626,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2813,8 +2650,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2837,8 +2674,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2854,9 +2691,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2911,74 +2748,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2991,8 +2809,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.213739Z", - "start_time": "2025-06-24T19:31:59.210358Z" + "end_time": "2025-06-26T20:17:08.683743Z", + "start_time": "2025-06-26T20:17:08.679403Z" } }, "source": [ @@ -3017,8 +2835,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -3041,7 +2859,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -3071,7 +2889,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -3112,8 +2930,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.287634Z", - "start_time": "2025-06-24T19:31:59.283037Z" + "end_time": "2025-06-26T20:17:08.756874Z", + "start_time": "2025-06-26T20:17:08.753678Z" } }, "source": [ @@ -3134,8 +2952,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ @@ -3181,8 +2999,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.345387Z", - "start_time": "2025-06-24T19:31:59.340713Z" + "end_time": "2025-06-26T20:17:08.825473Z", + "start_time": "2025-06-26T20:17:08.820372Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 4e387ef6..219269e0 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -298,8 +298,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -434,8 +434,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -472,8 +472,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -506,8 +506,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -525,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -547,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -572,8 +572,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -595,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -627,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -654,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -683,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -706,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -737,8 +737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -771,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -800,8 +800,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -839,8 +839,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -871,8 +871,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -892,8 +892,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -924,8 +924,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -942,8 +942,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -964,8 +964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -982,8 +982,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1033,8 +1033,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1062,8 +1062,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1093,8 +1093,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1133,8 +1133,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1170,8 +1170,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1197,8 +1197,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1221,8 +1221,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1244,8 +1244,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1273,8 +1273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1318,7 +1318,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1353,8 +1353,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1391,27 +1391,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1428,8 +1428,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1452,9 +1452,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1492,25 +1492,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1540,8 +1540,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1585,8 +1585,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1607,8 +1607,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1628,9 +1628,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1668,298 +1668,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -1994,8 +1831,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2013,7 +1850,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2039,8 +1876,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2051,7 +1888,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2068,8 +1905,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2110,7 +1947,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2127,8 +1964,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2147,7 +1984,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2194,8 +2031,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2215,8 +2052,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2235,8 +2072,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2283,8 +2120,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2306,8 +2143,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2332,8 +2169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2352,8 +2189,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2376,8 +2213,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2400,8 +2237,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2417,9 +2254,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2474,74 +2311,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2560,8 +2378,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2584,7 +2402,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2614,7 +2432,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2659,8 +2477,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index fa69aa58..6040564f 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -233,8 +233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -273,8 +273,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -297,8 +297,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -319,8 +319,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -345,8 +345,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -396,8 +396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -422,8 +422,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -447,8 +447,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -485,8 +485,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -519,8 +519,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -552,8 +552,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -573,8 +573,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -598,8 +598,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -621,8 +621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -653,8 +653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -680,8 +680,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -709,8 +709,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -732,8 +732,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -763,8 +763,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -797,8 +797,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -826,8 +826,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -865,8 +865,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -897,8 +897,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -918,8 +918,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -950,8 +950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -988,8 +988,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1009,8 +1009,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1043,8 +1043,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1060,8 +1060,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1101,8 +1101,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1130,8 +1130,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1161,8 +1161,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1201,8 +1201,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1238,8 +1238,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1265,8 +1265,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1289,8 +1289,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1312,8 +1312,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1372,8 +1372,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1386,7 +1386,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1421,8 +1421,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1459,27 +1459,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1496,8 +1496,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1520,9 +1520,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1560,25 +1560,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1608,8 +1608,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1653,8 +1653,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1694,8 +1694,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1729,8 +1729,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -1750,8 +1750,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -1769,7 +1769,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -1795,8 +1795,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -1807,7 +1807,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -1824,8 +1824,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -1866,7 +1866,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -1883,8 +1883,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -1903,7 +1903,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -1950,8 +1950,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -1971,8 +1971,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2008,8 +2008,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2037,8 +2037,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2071,8 +2071,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2092,8 +2092,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2118,8 +2118,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2154,8 +2154,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2175,8 +2175,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2199,8 +2199,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2216,9 +2216,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2273,74 +2273,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2359,8 +2340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2383,7 +2364,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2413,7 +2394,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2458,8 +2439,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index a34d330c..56db9c65 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -886,8 +886,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -925,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -957,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -978,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1010,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1048,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1065,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1087,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1121,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1138,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1163,8 +1163,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1204,8 +1204,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1264,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1368,8 +1368,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1392,8 +1392,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1415,8 +1415,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1444,8 +1444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1475,8 +1475,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1489,7 +1489,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1524,8 +1524,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1562,27 +1562,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1599,8 +1599,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1623,9 +1623,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1663,25 +1663,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1711,8 +1711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1756,8 +1756,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1797,8 +1797,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1816,8 +1816,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1837,9 +1837,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1877,298 +1877,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2199,8 +2036,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2220,8 +2057,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2239,7 +2076,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2277,7 +2114,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2294,8 +2131,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2336,7 +2173,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2353,8 +2190,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2373,7 +2210,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2420,8 +2257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2441,8 +2278,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2478,8 +2315,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2495,8 +2332,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2525,8 +2362,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2559,8 +2396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2576,8 +2413,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2599,8 +2436,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2625,8 +2462,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2661,8 +2498,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2678,8 +2515,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2702,8 +2539,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2726,8 +2563,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2743,9 +2580,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2800,74 +2637,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2886,8 +2704,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2910,7 +2728,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2940,7 +2758,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2985,8 +2803,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 4ab76338..6369d0f7 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -234,8 +234,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -274,8 +274,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -298,8 +298,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -320,8 +320,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -346,8 +346,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -376,8 +376,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -409,8 +409,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -434,8 +434,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -472,8 +472,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -506,8 +506,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -525,8 +525,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -547,8 +547,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -572,8 +572,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -595,8 +595,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -627,8 +627,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -654,8 +654,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -683,8 +683,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -706,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -737,8 +737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -771,8 +771,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -796,8 +796,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.360025Z", - "start_time": "2025-06-24T19:31:55.338112Z" + "end_time": "2025-06-26T20:17:04.810084Z", + "start_time": "2025-06-26T20:17:04.786754Z" } }, "source": [ @@ -818,8 +818,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -889,8 +889,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -910,8 +910,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -942,8 +942,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -960,8 +960,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -982,8 +982,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1000,8 +1000,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1025,8 +1025,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.652507Z", - "start_time": "2025-06-24T19:31:55.628692Z" + "end_time": "2025-06-26T20:17:05.104838Z", + "start_time": "2025-06-26T20:17:05.080097Z" } }, "source": [ @@ -1069,8 +1069,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1098,8 +1098,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1129,8 +1129,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1169,8 +1169,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1206,8 +1206,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1257,8 +1257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1280,8 +1280,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1309,8 +1309,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1340,8 +1340,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1354,7 +1354,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1389,8 +1389,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1427,27 +1427,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1464,8 +1464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1488,9 +1488,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1528,25 +1528,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1576,8 +1576,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1621,8 +1621,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1643,8 +1643,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1664,9 +1664,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1704,298 +1704,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2010,8 +1847,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.324104Z", - "start_time": "2025-06-24T19:31:58.321662Z" + "end_time": "2025-06-26T20:17:07.713878Z", + "start_time": "2025-06-26T20:17:07.711084Z" } }, "source": [ @@ -2050,8 +1887,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2069,7 +1906,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2095,8 +1932,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2107,7 +1944,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2120,8 +1957,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.533714Z", - "start_time": "2025-06-24T19:31:58.461636Z" + "end_time": "2025-06-26T20:17:08.014719Z", + "start_time": "2025-06-26T20:17:07.926032Z" } }, "source": [ @@ -2143,8 +1980,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2185,7 +2022,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2198,8 +2035,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.576962Z", - "start_time": "2025-06-24T19:31:58.573769Z" + "end_time": "2025-06-26T20:17:08.063578Z", + "start_time": "2025-06-26T20:17:08.060157Z" } }, "source": [ @@ -2221,8 +2058,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2241,7 +2078,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2288,8 +2125,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2309,8 +2146,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2329,8 +2166,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2347,8 +2184,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.762582Z", - "start_time": "2025-06-24T19:31:58.737160Z" + "end_time": "2025-06-26T20:17:08.275146Z", + "start_time": "2025-06-26T20:17:08.249526Z" } }, "source": [ @@ -2376,8 +2213,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2394,8 +2231,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2417,8 +2254,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2443,8 +2280,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2463,8 +2300,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2487,8 +2324,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2511,8 +2348,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2528,9 +2365,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2585,74 +2422,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2665,8 +2483,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.213739Z", - "start_time": "2025-06-24T19:31:59.210358Z" + "end_time": "2025-06-26T20:17:08.683743Z", + "start_time": "2025-06-26T20:17:08.679403Z" } }, "source": [ @@ -2691,8 +2509,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2715,7 +2533,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2745,7 +2563,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2786,8 +2604,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.287634Z", - "start_time": "2025-06-24T19:31:59.283037Z" + "end_time": "2025-06-26T20:17:08.756874Z", + "start_time": "2025-06-26T20:17:08.753678Z" } }, "source": [ @@ -2808,8 +2626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ @@ -2855,8 +2673,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.345387Z", - "start_time": "2025-06-24T19:31:59.340713Z" + "end_time": "2025-06-26T20:17:08.825473Z", + "start_time": "2025-06-26T20:17:08.820372Z" } }, "source": [ diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index a34d330c..56db9c65 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:51.625798Z", - "start_time": "2025-06-24T19:31:51.621877Z" + "end_time": "2025-06-26T20:17:01.034501Z", + "start_time": "2025-06-26T20:17:01.030269Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:52.254163Z", - "start_time": "2025-06-24T19:31:51.828427Z" + "end_time": "2025-06-26T20:17:01.631380Z", + "start_time": "2025-06-26T20:17:01.240873Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.053674Z", - "start_time": "2025-06-24T19:31:52.269805Z" + "end_time": "2025-06-26T20:17:03.331120Z", + "start_time": "2025-06-26T20:17:01.647431Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.167306Z", - "start_time": "2025-06-24T19:31:54.062903Z" + "end_time": "2025-06-26T20:17:03.461993Z", + "start_time": "2025-06-26T20:17:03.340761Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.179208Z", - "start_time": "2025-06-24T19:31:54.177035Z" + "end_time": "2025-06-26T20:17:03.473539Z", + "start_time": "2025-06-26T20:17:03.471144Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.191096Z", - "start_time": "2025-06-24T19:31:54.188112Z" + "end_time": "2025-06-26T20:17:03.493114Z", + "start_time": "2025-06-26T20:17:03.490661Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.207515Z", - "start_time": "2025-06-24T19:31:54.204470Z" + "end_time": "2025-06-26T20:17:03.516199Z", + "start_time": "2025-06-26T20:17:03.512942Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.224870Z", - "start_time": "2025-06-24T19:31:54.218012Z" + "end_time": "2025-06-26T20:17:03.551358Z", + "start_time": "2025-06-26T20:17:03.543942Z" } }, "source": [ @@ -315,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.238662Z", - "start_time": "2025-06-24T19:31:54.233640Z" + "end_time": "2025-06-26T20:17:03.572038Z", + "start_time": "2025-06-26T20:17:03.567506Z" } }, "source": [ @@ -337,8 +337,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.260417Z", - "start_time": "2025-06-24T19:31:54.248422Z" + "end_time": "2025-06-26T20:17:03.606045Z", + "start_time": "2025-06-26T20:17:03.591939Z" } }, "source": [ @@ -363,8 +363,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.290806Z", - "start_time": "2025-06-24T19:31:54.268045Z" + "end_time": "2025-06-26T20:17:03.643943Z", + "start_time": "2025-06-26T20:17:03.617017Z" } }, "source": [ @@ -414,8 +414,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.301750Z", - "start_time": "2025-06-24T19:31:54.299504Z" + "end_time": "2025-06-26T20:17:03.659010Z", + "start_time": "2025-06-26T20:17:03.655218Z" } }, "source": [ @@ -431,8 +431,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.320004Z", - "start_time": "2025-06-24T19:31:54.309474Z" + "end_time": "2025-06-26T20:17:03.684875Z", + "start_time": "2025-06-26T20:17:03.673453Z" } }, "source": [ @@ -464,8 +464,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.339399Z", - "start_time": "2025-06-24T19:31:54.328449Z" + "end_time": "2025-06-26T20:17:03.716786Z", + "start_time": "2025-06-26T20:17:03.705239Z" } }, "source": [ @@ -489,8 +489,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.368435Z", - "start_time": "2025-06-24T19:31:54.346808Z" + "end_time": "2025-06-26T20:17:03.746908Z", + "start_time": "2025-06-26T20:17:03.723650Z" } }, "source": [ @@ -527,8 +527,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.383971Z", - "start_time": "2025-06-24T19:31:54.375760Z" + "end_time": "2025-06-26T20:17:03.762882Z", + "start_time": "2025-06-26T20:17:03.753179Z" } }, "source": [ @@ -561,8 +561,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.394877Z", - "start_time": "2025-06-24T19:31:54.391652Z" + "end_time": "2025-06-26T20:17:03.774984Z", + "start_time": "2025-06-26T20:17:03.771782Z" } }, "source": [ @@ -594,8 +594,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.406228Z", - "start_time": "2025-06-24T19:31:54.403906Z" + "end_time": "2025-06-26T20:17:03.788343Z", + "start_time": "2025-06-26T20:17:03.786044Z" } }, "source": [ @@ -611,8 +611,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.417559Z", - "start_time": "2025-06-24T19:31:54.414462Z" + "end_time": "2025-06-26T20:17:03.809066Z", + "start_time": "2025-06-26T20:17:03.806273Z" } }, "source": [ @@ -633,8 +633,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.434638Z", - "start_time": "2025-06-24T19:31:54.429537Z" + "end_time": "2025-06-26T20:17:03.832036Z", + "start_time": "2025-06-26T20:17:03.827498Z" } }, "source": [ @@ -658,8 +658,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.448099Z", - "start_time": "2025-06-24T19:31:54.444761Z" + "end_time": "2025-06-26T20:17:03.870751Z", + "start_time": "2025-06-26T20:17:03.867184Z" } }, "source": [ @@ -681,8 +681,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.480416Z", - "start_time": "2025-06-24T19:31:54.459619Z" + "end_time": "2025-06-26T20:17:03.930448Z", + "start_time": "2025-06-26T20:17:03.908145Z" } }, "source": [ @@ -713,8 +713,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.491966Z", - "start_time": "2025-06-24T19:31:54.488552Z" + "end_time": "2025-06-26T20:17:03.948996Z", + "start_time": "2025-06-26T20:17:03.945721Z" } }, "source": [ @@ -740,8 +740,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.510661Z", - "start_time": "2025-06-24T19:31:54.507100Z" + "end_time": "2025-06-26T20:17:03.977346Z", + "start_time": "2025-06-26T20:17:03.974044Z" } }, "source": [ @@ -769,8 +769,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.534099Z", - "start_time": "2025-06-24T19:31:54.531585Z" + "end_time": "2025-06-26T20:17:04.000678Z", + "start_time": "2025-06-26T20:17:03.998071Z" } }, "source": [ @@ -792,8 +792,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:54.557278Z", - "start_time": "2025-06-24T19:31:54.554745Z" + "end_time": "2025-06-26T20:17:04.039083Z", + "start_time": "2025-06-26T20:17:04.036119Z" } }, "source": [ @@ -823,8 +823,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.298145Z", - "start_time": "2025-06-24T19:31:54.575470Z" + "end_time": "2025-06-26T20:17:04.750407Z", + "start_time": "2025-06-26T20:17:04.060666Z" } }, "source": [ @@ -857,8 +857,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.328653Z", - "start_time": "2025-06-24T19:31:55.306276Z" + "end_time": "2025-06-26T20:17:04.782300Z", + "start_time": "2025-06-26T20:17:04.758266Z" } }, "source": [ @@ -886,8 +886,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.377191Z", - "start_time": "2025-06-24T19:31:55.372584Z" + "end_time": "2025-06-26T20:17:04.826906Z", + "start_time": "2025-06-26T20:17:04.822382Z" } }, "source": [ @@ -925,8 +925,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.398733Z", - "start_time": "2025-06-24T19:31:55.393659Z" + "end_time": "2025-06-26T20:17:04.842149Z", + "start_time": "2025-06-26T20:17:04.838049Z" } }, "source": [ @@ -957,8 +957,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.421506Z", - "start_time": "2025-06-24T19:31:55.418367Z" + "end_time": "2025-06-26T20:17:04.869153Z", + "start_time": "2025-06-26T20:17:04.866639Z" } }, "source": [ @@ -978,8 +978,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.453218Z", - "start_time": "2025-06-24T19:31:55.448353Z" + "end_time": "2025-06-26T20:17:04.897870Z", + "start_time": "2025-06-26T20:17:04.892755Z" } }, "source": [ @@ -1010,8 +1010,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.477166Z", - "start_time": "2025-06-24T19:31:55.473650Z" + "end_time": "2025-06-26T20:17:04.928993Z", + "start_time": "2025-06-26T20:17:04.925962Z" } }, "source": [ @@ -1048,8 +1048,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.503091Z", - "start_time": "2025-06-24T19:31:55.500190Z" + "end_time": "2025-06-26T20:17:04.960513Z", + "start_time": "2025-06-26T20:17:04.957441Z" } }, "source": [ @@ -1065,8 +1065,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.544924Z", - "start_time": "2025-06-24T19:31:55.541593Z" + "end_time": "2025-06-26T20:17:04.983292Z", + "start_time": "2025-06-26T20:17:04.979234Z" } }, "source": [ @@ -1087,8 +1087,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.563038Z", - "start_time": "2025-06-24T19:31:55.560499Z" + "end_time": "2025-06-26T20:17:05.010085Z", + "start_time": "2025-06-26T20:17:05.007330Z" } }, "source": [ @@ -1121,8 +1121,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.579334Z", - "start_time": "2025-06-24T19:31:55.577111Z" + "end_time": "2025-06-26T20:17:05.029655Z", + "start_time": "2025-06-26T20:17:05.025814Z" } }, "source": [ @@ -1138,8 +1138,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.624668Z", - "start_time": "2025-06-24T19:31:55.601688Z" + "end_time": "2025-06-26T20:17:05.070096Z", + "start_time": "2025-06-26T20:17:05.046307Z" } }, "source": [ @@ -1163,8 +1163,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.664812Z", - "start_time": "2025-06-24T19:31:55.662484Z" + "end_time": "2025-06-26T20:17:05.114892Z", + "start_time": "2025-06-26T20:17:05.112840Z" } }, "source": [], @@ -1204,8 +1204,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.683525Z", - "start_time": "2025-06-24T19:31:55.678196Z" + "end_time": "2025-06-26T20:17:05.137429Z", + "start_time": "2025-06-26T20:17:05.132086Z" } }, "source": [ @@ -1233,8 +1233,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.701611Z", - "start_time": "2025-06-24T19:31:55.698137Z" + "end_time": "2025-06-26T20:17:05.151129Z", + "start_time": "2025-06-26T20:17:05.147972Z" } }, "source": [ @@ -1264,8 +1264,8 @@ "metadata": { "scrolled": true, "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.722499Z", - "start_time": "2025-06-24T19:31:55.719447Z" + "end_time": "2025-06-26T20:17:05.173772Z", + "start_time": "2025-06-26T20:17:05.170619Z" } }, "source": [ @@ -1304,8 +1304,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.752786Z", - "start_time": "2025-06-24T19:31:55.746899Z" + "end_time": "2025-06-26T20:17:05.228588Z", + "start_time": "2025-06-26T20:17:05.223424Z" } }, "source": [ @@ -1341,8 +1341,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.778192Z", - "start_time": "2025-06-24T19:31:55.774682Z" + "end_time": "2025-06-26T20:17:05.266556Z", + "start_time": "2025-06-26T20:17:05.263086Z" } }, "source": [ @@ -1368,8 +1368,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.795822Z", - "start_time": "2025-06-24T19:31:55.793437Z" + "end_time": "2025-06-26T20:17:05.283753Z", + "start_time": "2025-06-26T20:17:05.281507Z" } }, "source": [ @@ -1392,8 +1392,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.816947Z", - "start_time": "2025-06-24T19:31:55.814431Z" + "end_time": "2025-06-26T20:17:05.310090Z", + "start_time": "2025-06-26T20:17:05.306928Z" } }, "source": [ @@ -1415,8 +1415,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.860044Z", - "start_time": "2025-06-24T19:31:55.834336Z" + "end_time": "2025-06-26T20:17:05.352272Z", + "start_time": "2025-06-26T20:17:05.329055Z" } }, "source": [ @@ -1444,8 +1444,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.885959Z", - "start_time": "2025-06-24T19:31:55.864176Z" + "end_time": "2025-06-26T20:17:05.394094Z", + "start_time": "2025-06-26T20:17:05.363031Z" } }, "source": [ @@ -1475,8 +1475,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:55.937458Z", - "start_time": "2025-06-24T19:31:55.892147Z" + "end_time": "2025-06-26T20:17:05.473532Z", + "start_time": "2025-06-26T20:17:05.422203Z" } }, "source": [ @@ -1489,7 +1489,7 @@ " (0, \"Vap\", \"benzene\"): 1e-5,\n", " (0, \"Vap\", \"toluene\"): 1e-5,\n", " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " (0, \"Vap\", \"hydrogen\"): 0.5,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1524,8 +1524,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.330990Z", - "start_time": "2025-06-24T19:31:55.948780Z" + "end_time": "2025-06-26T20:17:07.120417Z", + "start_time": "2025-06-26T20:17:05.497326Z" } }, "source": [ @@ -1562,27 +1562,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-24 12:31:56 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-24 12:31:57 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" + "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", + "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", + "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" ] } ], @@ -1599,8 +1599,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.422312Z", - "start_time": "2025-06-24T19:31:57.340180Z" + "end_time": "2025-06-26T20:17:07.215113Z", + "start_time": "2025-06-26T20:17:07.128960Z" } }, "source": [ @@ -1623,9 +1623,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpnmv6i5ck_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1663,25 +1663,25 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.56e+04 7.06e+02 -1.0 3.97e+03 - 8.60e-01 1.05e-01h 1\n", - " 2 0.0000000e+00 5.55e+04 1.89e+03 -1.0 4.15e+02 - 9.93e-01 4.60e-01h 1\n", - " 3 0.0000000e+00 3.34e+04 1.62e+05 -1.0 2.27e+02 - 1.00e+00 5.02e-01h 1\n", - " 4 0.0000000e+00 6.61e+03 1.47e+09 -1.0 1.29e+02 - 1.00e+00 9.71e-01h 1\n", - " 5 0.0000000e+00 3.60e+03 3.02e+08 -1.0 1.29e+02 - 1.00e+00 4.55e-01h 2\n", - " 6 0.0000000e+00 1.87e+02 1.63e+09 -1.0 7.07e+01 - 1.00e+00 9.49e-01h 1\n", - " 7 0.0000000e+00 5.61e+01 6.71e+08 -1.0 3.90e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 2.83e-02 5.59e+05 -1.0 7.47e-04 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 5.22e-08 2.21e-01 -1.0 7.02e-09 - 1.00e+00 1.00e+00h 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", + " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", + " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", + " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", + " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", + " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", + " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", + " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", + " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", "\n", "Number of Iterations....: 9\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 5.2154064178466790e-08\n", + "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", "\n", "\n", "Number of objective function evaluations = 12\n", @@ -1711,8 +1711,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.464844Z", - "start_time": "2025-06-24T19:31:57.440973Z" + "end_time": "2025-06-26T20:17:07.250825Z", + "start_time": "2025-06-26T20:17:07.225571Z" } }, "source": [ @@ -1756,8 +1756,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.483016Z", - "start_time": "2025-06-24T19:31:57.480415Z" + "end_time": "2025-06-26T20:17:07.264286Z", + "start_time": "2025-06-26T20:17:07.261233Z" } }, "source": [ @@ -1797,8 +1797,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:57.510879Z", - "start_time": "2025-06-24T19:31:57.508276Z" + "end_time": "2025-06-26T20:17:07.289757Z", + "start_time": "2025-06-26T20:17:07.286635Z" } }, "source": [ @@ -1816,8 +1816,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.312733Z", - "start_time": "2025-06-24T19:31:57.533935Z" + "end_time": "2025-06-26T20:17:07.696793Z", + "start_time": "2025-06-26T20:17:07.319999Z" } }, "source": [ @@ -1837,9 +1837,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpp3_hscv2_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -1877,298 +1877,135 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 9.02e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 8.91e+04 2.71e+01 -1.0 1.70e+04 - 1.08e-02 7.31e-03h 2\n", - " 2 0.0000000e+00 8.84e+04 7.33e+01 -1.0 1.74e+04 - 5.47e-02 4.09e-03h 2\n", - " 3 0.0000000e+00 9.12e+04 3.04e+04 -1.0 1.76e+04 - 3.32e-02 4.38e-03h 1\n", - " 4 0.0000000e+00 9.21e+04 6.13e+05 -1.0 2.03e+04 - 3.78e-01 1.45e-04h 1\n", - " 5r 0.0000000e+00 9.21e+04 9.99e+02 0.3 0.00e+00 - 0.00e+00 3.70e-07R 3\n", - " 6r 0.0000000e+00 7.72e+04 2.04e+03 0.3 1.98e+03 - 5.27e-04 9.72e-04f 1\n", - " 7r 0.0000000e+00 7.68e+04 2.22e+03 0.3 5.34e+02 - 3.37e-03 1.49e-03f 1\n", - " 8r 0.0000000e+00 7.63e+04 1.62e+03 0.3 2.17e+02 - 5.38e-03 4.73e-03f 1\n", - " 9r 0.0000000e+00 7.16e+04 3.37e+03 0.3 3.36e+02 - 2.94e-02 1.34e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 7.28e+04 2.13e+03 0.3 2.64e+02 - 3.03e-02 4.06e-02f 1\n", - " 11r 0.0000000e+00 2.09e+05 3.66e+03 0.3 3.24e+02 - 7.43e-02 8.19e-02f 1\n", - " 12r 0.0000000e+00 2.72e+05 4.43e+03 0.3 2.58e+02 - 2.52e-01 8.18e-02f 1\n", - " 13r 0.0000000e+00 2.95e+05 5.68e+03 0.3 1.73e+01 - 5.54e-01 1.61e-01f 1\n", - " 14r 0.0000000e+00 3.07e+05 2.91e+03 0.3 5.68e+00 - 1.32e-01 4.14e-01f 1\n", - " 15r 0.0000000e+00 1.91e+05 1.13e+03 0.3 5.37e+00 - 7.87e-01 1.00e+00f 1\n", - " 16r 0.0000000e+00 1.26e+05 1.43e+03 0.3 9.51e+00 - 8.13e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 1.24e+05 8.01e+02 0.3 9.45e+00 - 5.18e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 1.17e+05 8.20e+02 0.3 7.85e+00 - 7.45e-01 1.00e+00f 1\n", - " 19r 0.0000000e+00 1.09e+05 4.13e+02 0.3 7.85e+00 - 7.01e-01 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 1.04e+05 4.11e+02 0.3 4.52e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 1.03e+05 4.83e+02 0.3 7.55e+00 - 1.00e+00 1.00e+00f 1\n", - " 22r 0.0000000e+00 1.03e+05 1.06e+01 0.3 4.49e+00 - 1.00e+00 1.00e+00H 1\n", - " 23r 0.0000000e+00 1.53e+05 2.66e+03 -1.1 2.86e+01 - 9.40e-01 4.09e-01f 1\n", - " 24r 0.0000000e+00 1.29e+05 4.09e+03 -1.1 5.10e+01 - 1.00e+00 3.20e-01f 1\n", - " 25r 0.0000000e+00 3.99e+04 4.33e+03 -1.1 3.47e+01 - 1.00e+00 8.31e-01f 1\n", - " 26r 0.0000000e+00 3.75e+04 1.23e+04 -1.1 7.85e+00 - 1.00e+00 1.00e+00f 1\n", - " 27r 0.0000000e+00 3.56e+04 6.29e+02 -1.1 7.19e-01 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 2.06e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.26e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.14e-01 - 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 3.56e+04 5.66e+00 -1.1 1.13e-01 - 1.00e+00 1.00e+00H 1\n", - " 32r 0.0000000e+00 3.56e+04 5.72e+00 -1.1 1.07e-01 - 1.00e+00 1.00e+00H 1\n", - " 33r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.68e-01 - 1.00e+00 1.00e+00H 1\n", - " 34r 0.0000000e+00 3.56e+04 5.38e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 35r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.24e-01 - 1.00e+00 1.00e+00H 1\n", - " 36r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.11e-01 - 1.00e+00 1.00e+00h 1\n", - " 37r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.10e-01 - 1.00e+00 1.00e+00H 1\n", - " 38r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.20e-01 - 1.00e+00 1.00e+00H 1\n", - " 39r 0.0000000e+00 3.56e+04 5.70e+00 -1.1 1.63e-01 - 1.00e+00 1.00e+00H 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 3.56e+04 5.39e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 41r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.03e-01 - 1.00e+00 1.00e+00H 1\n", - " 42r 0.0000000e+00 3.56e+04 6.06e+00 -1.1 2.30e-01 - 1.00e+00 2.50e-01h 3\n", - " 43r 0.0000000e+00 3.56e+04 5.71e+00 -1.1 1.09e-01 - 1.00e+00 1.00e+00H 1\n", - " 44r 0.0000000e+00 3.56e+04 2.16e+00 -1.1 1.02e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 3.55e+04 6.30e+03 -1.8 3.41e+00 - 9.02e-01 8.42e-01f 1\n", - " 46r 0.0000000e+00 3.43e+04 1.16e+04 -1.8 7.74e+01 - 1.00e+00 1.00e+00f 1\n", - " 47r 0.0000000e+00 3.40e+04 5.59e+01 -1.8 2.22e+00 - 1.00e+00 1.00e+00h 1\n", - " 48r 0.0000000e+00 3.40e+04 3.86e+00 -1.8 1.86e-01 - 1.00e+00 1.00e+00h 1\n", - " 49r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 51r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 52r 0.0000000e+00 3.40e+04 3.93e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00H 1\n", - " 53r 0.0000000e+00 3.40e+04 3.07e+00 -1.8 3.71e-02 - 1.00e+00 1.00e+00h 1\n", - " 54r 0.0000000e+00 3.40e+04 2.45e+00 -1.8 2.31e-02 - 1.00e+00 1.00e+00h 1\n", - " 55r 0.0000000e+00 3.40e+04 2.17e+00 -1.8 2.31e-02 - 1.00e+00 5.00e-01h 2\n", - " 56r 0.0000000e+00 3.40e+04 2.50e+00 -1.8 5.74e-03 - 1.00e+00 1.00e+00h 1\n", - " 57r 0.0000000e+00 3.40e+04 2.31e+00 -1.8 1.07e-02 - 1.00e+00 1.00e+00h 1\n", - " 58r 0.0000000e+00 3.40e+04 5.82e+00 -1.8 2.18e-02 - 1.00e+00 1.00e+00H 1\n", - " 59r 0.0000000e+00 3.40e+04 4.11e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 3.40e+04 1.90e+00 -1.8 1.06e-02 - 1.00e+00 5.00e-01h 2\n", - " 61r 0.0000000e+00 3.40e+04 5.61e+00 -1.8 1.60e-02 - 1.00e+00 1.00e+00H 1\n", - " 62r 0.0000000e+00 3.40e+04 2.49e+00 -1.8 2.17e-02 - 1.00e+00 1.00e+00h 1\n", - " 63r 0.0000000e+00 3.40e+04 2.12e+00 -1.8 2.35e-02 - 1.00e+00 5.00e-01h 2\n", - " 64r 0.0000000e+00 3.40e+04 2.63e+00 -1.8 5.40e-03 - 1.00e+00 1.00e+00h 1\n", - " 65r 0.0000000e+00 3.40e+04 1.77e+00 -1.8 1.36e-02 - 1.00e+00 5.00e-01h 2\n", - " 66r 0.0000000e+00 3.40e+04 5.63e+00 -1.8 1.48e-02 - 1.00e+00 1.00e+00H 1\n", - " 67r 0.0000000e+00 3.40e+04 3.98e+00 -1.8 2.18e-02 - 1.00e+00 5.00e-01h 2\n", - " 68r 0.0000000e+00 3.40e+04 2.57e+00 -1.8 9.18e-03 - 1.00e+00 2.50e-01h 3\n", - " 69r 0.0000000e+00 3.40e+04 1.30e+00 -1.8 7.86e-04 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 3.40e+04 3.60e-01 -1.8 5.85e-04 - 1.00e+00 1.00e+00h 1\n", - " 71r 0.0000000e+00 3.40e+04 3.41e+04 -2.7 2.65e+00 - 8.41e-01 6.77e-01f 1\n", - " 72r 0.0000000e+00 3.91e+06 4.04e+04 -2.7 5.66e+02 -4.0 3.59e-01 4.72e-01f 1\n", - " 73r 0.0000000e+00 3.90e+06 8.56e+04 -2.7 3.82e-01 1.8 1.00e+00 9.37e-04f 1\n", - " 74r 0.0000000e+00 4.01e+06 8.32e+04 -2.7 4.46e+00 1.4 1.04e-01 1.40e-02f 1\n", - " 75r 0.0000000e+00 3.81e+06 9.63e+04 -2.7 2.55e+02 - 1.25e-01 5.14e-02f 1\n", - " 76r 0.0000000e+00 3.80e+06 9.22e+04 -2.7 8.19e-01 0.9 3.56e-02 1.71e-03f 1\n", - " 77r 0.0000000e+00 3.78e+06 9.45e+04 -2.7 1.99e+01 0.4 8.56e-06 4.94e-03h 1\n", - " 78r 0.0000000e+00 3.78e+06 7.94e+04 -2.7 6.37e+02 - 2.71e-03 1.29e-02f 1\n", - " 79r 0.0000000e+00 3.77e+06 4.66e+04 -2.7 6.22e+02 - 9.55e-01 2.39e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 8.88e+05 9.38e+03 -2.7 2.39e+02 - 3.49e-01 7.80e-01f 1\n", - " 81r 0.0000000e+00 9.86e+05 8.72e+03 -2.7 5.73e+00 -0.1 1.25e-02 3.76e-02h 1\n", - " 82r 0.0000000e+00 2.09e+04 1.49e+04 -2.7 7.68e-02 0.4 5.14e-02 1.00e+00h 1\n", - " 83r 0.0000000e+00 1.17e+04 5.00e+02 -2.7 2.84e-02 0.8 9.69e-01 1.00e+00h 1\n", - " 84r 0.0000000e+00 1.17e+04 6.92e-01 -2.7 1.07e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 85r 0.0000000e+00 1.17e+04 1.03e+01 -2.7 4.00e-03 1.6 1.00e+00 1.00e+00h 1\n", - " 86r 0.0000000e+00 1.17e+04 1.53e+00 -2.7 1.20e-02 1.2 1.00e+00 1.00e+00h 1\n", - " 87r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 3.60e-02 0.7 1.00e+00 1.00e+00f 1\n", - " 88r 0.0000000e+00 1.74e+04 1.74e-01 -2.7 1.08e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 89r 0.0000000e+00 2.20e+04 1.74e-01 -2.7 3.23e-01 -0.3 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 1.17e+04 1.74e-01 -2.7 1.21e-01 0.2 1.00e+00 1.00e+00f 1\n", - " 91r 0.0000000e+00 1.17e+04 4.47e-01 -2.7 3.64e-01 -0.3 1.00e+00 1.00e+00f 1\n", - " 92r 0.0000000e+00 1.17e+04 7.28e-01 -2.7 1.36e-01 0.1 1.00e+00 1.00e+00f 1\n", - " 93r 0.0000000e+00 1.17e+04 9.61e-01 -2.7 5.11e-02 0.5 1.00e+00 1.00e+00f 1\n", - " 94r 0.0000000e+00 1.17e+04 4.11e-01 -2.7 1.92e-02 1.0 1.00e+00 1.00e+00h 1\n", - " 95r 0.0000000e+00 1.17e+04 1.35e+01 -2.7 7.19e-03 1.4 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 1.17e+04 2.08e+00 -2.7 2.16e-02 0.9 1.00e+00 1.00e+00h 1\n", - " 97r 0.0000000e+00 1.17e+04 1.22e+02 -2.7 5.10e+02 - 1.00e+00 6.37e-02f 1\n", - " 98r 0.0000000e+00 1.17e+04 1.34e+03 -2.7 4.93e+01 - 1.00e+00 3.82e-03f 2\n", - " 99r 0.0000000e+00 1.85e+05 9.95e-01 -2.7 4.80e+01 - 1.00e+00 1.00e+00f 1\n", + " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", + " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", + " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", + " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", + " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", + " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", + " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", + " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", + " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 100r 0.0000000e+00 1.17e+04 4.36e-02 -2.7 1.62e-02 0.4 1.00e+00 1.00e+00h 1\n", - " 101r 0.0000000e+00 6.98e+05 2.63e+03 -4.1 2.34e+00 - 2.85e-01 5.08e-01f 1\n", - " 102r 0.0000000e+00 1.12e+05 1.63e+03 -4.1 1.49e+03 - 1.00e+00 8.42e-01f 1\n", - " 103r 0.0000000e+00 1.11e+04 4.24e+00 -4.1 2.35e+02 - 1.00e+00 1.00e+00f 1\n", - " 104r 0.0000000e+00 1.11e+04 6.14e-02 -4.1 7.09e-03 - 1.00e+00 1.00e+00h 1\n", - " 105r 0.0000000e+00 1.11e+04 1.78e-04 -4.1 9.78e-04 - 1.00e+00 1.00e+00h 1\n", - " 106r 0.0000000e+00 1.11e+04 1.71e+02 -6.1 1.43e-01 - 1.00e+00 8.13e-01f 1\n", - " 107r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 1.78e+04 - 8.51e-01 5.59e-01f 1\n", - " 108r 0.0000000e+00 2.35e+05 9.95e+01 -6.1 8.02e+03 - 4.26e-05 7.29e-04f 1\n", - " 109r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 5.36e-07 5.23e-05f 1\n", + " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", + " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", + " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", + " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", + " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", + " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", + " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", + " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 110r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.40e+03 - 2.21e-06 9.49e-05f 1\n", - " 111r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.83e+03 - 3.19e-06 8.46e-05f 1\n", - " 112r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.27e+03 - 3.80e-06 8.00e-05f 1\n", - " 113r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.82e+03 - 7.43e-06 7.33e-05f 1\n", - " 114r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 8.13e+03 - 8.98e-06 6.51e-05f 1\n", - " 115r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.80e+03 - 2.66e-05 5.51e-05f 1\n", - " 116r 0.0000000e+00 2.35e+05 9.94e+01 -6.1 7.98e+03 - 3.50e-05 4.29e-05f 1\n", - " 117r 0.0000000e+00 2.35e+05 3.58e+02 -6.1 7.72e+03 - 9.91e-01 2.92e-05f 1\n", - " 118r 0.0000000e+00 2.34e+05 4.20e+02 -6.1 3.46e+03 - 1.00e+00 5.57e-03f 1\n", - " 119r 0.0000000e+00 1.39e+05 2.81e+01 -6.1 3.44e+03 - 1.00e+00 9.44e-01f 1\n", + " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", + " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", + " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", + " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", + " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", + " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", + " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", + " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", + " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 120r 0.0000000e+00 3.14e+03 2.60e-02 -6.1 1.92e+02 - 1.00e+00 1.00e+00f 1\n", - " 121r 0.0000000e+00 3.14e+03 4.00e-07 -6.1 1.07e-03 - 1.00e+00 1.00e+00h 1\n", - " 122r 0.0000000e+00 3.14e+03 1.04e+01 -9.0 2.08e-02 - 1.00e+00 8.99e-01f 1\n", - " 123r 0.0000000e+00 1.10e+05 1.51e+02 -9.0 2.47e+05 - 2.56e-01 1.28e-02f 1\n", - " 124r 0.0000000e+00 7.70e+04 8.48e+01 -9.0 9.49e+03 - 2.62e-01 3.07e-01f 1\n", - " 125r 0.0000000e+00 7.46e+04 4.12e+02 -9.0 7.79e+03 - 7.15e-01 6.30e-02h 1\n", - " 126r 0.0000000e+00 1.65e+04 1.68e+02 -9.0 1.49e+02 - 1.00e+00 7.81e-01h 1\n", - " 127r 0.0000000e+00 1.02e+05 1.29e+02 -9.0 1.47e+02 - 1.00e+00 1.00e+00h 1\n", - " 128r 0.0000000e+00 6.41e+04 5.08e+02 -9.0 1.62e+00 - 2.39e-01 3.98e-01h 1\n", - " 129r 0.0000000e+00 6.40e+04 9.17e+02 -9.0 2.61e+03 - 4.77e-03 3.44e-04h 1\n", + " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", + " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", + " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", + " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", + " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", + " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", + " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", + " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", + " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 130r 0.0000000e+00 6.40e+04 9.93e+02 -9.0 9.49e-01 -0.0 0.00e+00 5.66e-10R 8\n", - " 131r 0.0000000e+00 6.38e+04 9.93e+02 -9.0 1.36e+02 -0.5 2.39e-05 2.74e-05f 1\n", - " 132r 0.0000000e+00 5.87e+04 9.93e+02 -9.0 1.39e+02 -1.0 4.39e-06 7.26e-04f 4\n", - " 133r 0.0000000e+00 5.85e+04 9.93e+02 -9.0 1.26e+02 -0.6 2.27e-04 2.23e-05f 1\n", - " 134r 0.0000000e+00 5.85e+04 9.92e+02 -9.0 1.26e+02 -1.1 6.09e-03 1.14e-05f 1\n", - " 135r 0.0000000e+00 5.35e+04 9.92e+02 -9.0 1.46e+02 -1.5 1.46e-04 8.05e-04f 4\n", - " 136r 0.0000000e+00 5.15e+04 9.93e+02 -9.0 3.91e+02 -2.0 5.53e-05 2.98e-04f 3\n", - " 137r 0.0000000e+00 5.13e+04 9.92e+02 -9.0 4.84e+01 1.1 6.44e-04 1.05e-04f 1\n", - " 138r 0.0000000e+00 5.02e+04 9.92e+02 -9.0 7.37e+01 0.7 3.84e-04 2.74e-04f 4\n", - " 139r 0.0000000e+00 4.90e+04 9.90e+02 -9.0 4.95e+01 1.1 1.55e-03 6.20e-04f 1\n", + " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", + " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", + " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", + " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", + " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", + " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", + " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", + " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", + " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 140r 0.0000000e+00 4.70e+04 9.89e+02 -9.0 6.84e+01 0.6 6.11e-03 6.06e-04f 1\n", - " 141r 0.0000000e+00 4.44e+04 9.90e+02 -9.0 7.34e+01 0.1 7.57e-08 7.11e-04f 1\n", - " 142r 0.0000000e+00 4.20e+04 9.90e+02 -9.0 7.37e+01 -0.4 2.38e-05 6.66e-04f 3\n", - " 143r 0.0000000e+00 3.89e+04 9.90e+02 -9.0 7.14e+01 -0.8 5.18e-04 8.78e-04f 2\n", - " 144r 0.0000000e+00 3.78e+04 9.90e+02 -9.0 6.30e+01 -0.4 4.35e-05 3.65e-04f 3\n", - " 145r 0.0000000e+00 3.74e+04 9.87e+02 -9.0 1.40e+01 1.8 8.32e-03 6.67e-04f 1\n", - " 146r 0.0000000e+00 3.58e+04 9.85e+02 -9.0 2.71e+01 1.3 2.99e-03 1.20e-03f 4\n", - " 147r 0.0000000e+00 3.55e+04 9.85e+02 -9.0 3.70e+01 0.9 2.85e-04 1.69e-04f 7\n", - " 148r 0.0000000e+00 3.55e+04 9.84e+02 -9.0 2.65e+01 1.3 3.70e-04 4.38e-05f 5\n", - " 149r 0.0000000e+00 3.52e+04 9.84e+02 -9.0 1.53e+01 1.7 1.83e-03 3.61e-04f 1\n", + " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", + " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", + " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", + " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", + " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", + " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", + " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", + " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", + " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", + " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 150r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 2.76e+01 1.2 7.93e-06 4.25e-04f 7\n", - " 151r 0.0000000e+00 3.46e+04 9.84e+02 -9.0 1.64e+01 1.7 6.10e-03 1.54e-06f 1\n", - " 152r 0.0000000e+00 3.41e+04 9.84e+02 -9.0 2.84e+01 1.2 1.34e-03 3.82e-04f 6\n", - " 153r 0.0000000e+00 3.41e+04 1.01e+03 -9.0 1.74e+01 1.6 1.21e-03 4.89e-05f 8\n", - " 154r 0.0000000e+00 3.39e+04 9.83e+02 -9.0 2.90e+01 1.1 2.96e-03 1.09e-04f 8\n", - " 155r 0.0000000e+00 3.37e+04 9.83e+02 -9.0 1.85e+01 1.6 8.37e-03 2.27e-04f 1\n", - " 156r 0.0000000e+00 3.34e+04 9.83e+02 -9.0 2.97e+01 1.1 8.17e-06 2.32e-04f 7\n", - " 157r 0.0000000e+00 3.34e+04 1.05e+03 -9.0 1.96e+01 1.5 5.28e-03 7.90e-07f 1\n", - " 158r 0.0000000e+00 3.32e+04 9.83e+02 -9.0 3.03e+01 1.0 3.24e-03 1.74e-04f 8\n", - " 159r 0.0000000e+00 3.31e+04 9.84e+02 -9.0 2.06e+01 1.5 7.39e-04 4.56e-05f 7\n", + " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", + " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", + " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", + " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", + " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", + " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", + " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", + " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", + " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", + " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 160r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 3.09e+01 1.0 4.54e-04 6.12e-05f 9\n", - " 161r 0.0000000e+00 3.30e+04 9.83e+02 -9.0 2.17e+01 1.4 1.27e-02 7.17e-05f 9\n", - " 162r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 1.22e+01 1.8 1.44e-02 2.81e-04f 1\n", - " 163r 0.0000000e+00 3.28e+04 9.83e+02 -9.0 2.28e+01 1.4 4.67e-05 1.13e-05f 1\n", - " 164r 0.0000000e+00 3.25e+04 9.83e+02 -9.0 3.21e+01 0.9 8.20e-05 1.75e-04f 8\n", - " 165r 0.0000000e+00 3.25e+04 2.03e+03 -9.0 6.17e+00 2.2 9.21e-03 1.93e-08f 1\n", - " 166r 0.0000000e+00 3.20e+04 2.62e+03 -9.0 1.41e+01 1.7 4.97e-02 7.90e-04f 7\n", - " 167r 0.0000000e+00 3.19e+04 2.48e+03 -9.0 2.43e+01 1.3 7.95e-03 1.13e-04f 9\n", - " 168r 0.0000000e+00 3.17e+04 1.63e+03 -9.0 3.21e+01 0.8 1.65e-02 8.53e-05f 9\n", - " 169r 0.0000000e+00 3.17e+04 9.82e+02 -9.0 3.57e+01 0.3 6.04e-03 3.82e-05f 10\n", + " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", + " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", + " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", + " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", + " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", + " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", + " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", + " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", + " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", + " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 170r 0.0000000e+00 3.16e+04 9.82e+02 -9.0 3.24e+01 0.7 3.86e-10 1.02e-05f 8\n", - " 171r 0.0000000e+00 3.16e+04 1.06e+03 -9.0 8.15e+00 2.1 3.17e-03 7.52e-06f 1\n", - " 172r 0.0000000e+00 2.65e+04 1.21e+03 -9.0 1.71e+01 1.6 5.83e-02 5.99e-03f 1\n", - " 173r 0.0000000e+00 1.18e+04 1.95e+03 -9.0 2.13e+01 1.1 6.23e-03 2.79e-02f 1\n", - " 174r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 1.62e+00 0.6 4.40e-02 1.42e-04f 1\n", - " 175r 0.0000000e+00 1.18e+04 4.78e+03 -9.0 9.50e-02 2.0 9.25e-04 7.42e-04f 1\n", - " 176r 0.0000000e+00 1.17e+04 4.78e+03 -9.0 4.66e-02 2.4 5.68e-04 9.48e-04f 1\n", - " 177r 0.0000000e+00 1.17e+04 4.77e+03 -9.0 7.17e-02 1.9 3.24e-03 4.50e-04f 1\n", - " 178r 0.0000000e+00 1.17e+04 4.76e+03 -9.0 2.10e-01 1.4 6.16e-04 2.91e-03f 1\n", - " 179r 0.0000000e+00 1.17e+04 4.74e+03 -9.0 5.51e-02 2.8 8.44e-04 4.72e-03f 1\n", + " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", + " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", + " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", + " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", + " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", + " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", + " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", + " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", + " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", + " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 180r 0.0000000e+00 1.16e+04 7.64e+03 -9.0 1.16e-02 3.2 1.15e-02 6.16e-02f 1\n", - " 181r 0.0000000e+00 1.10e+04 7.13e+03 -9.0 3.63e-02 2.7 2.35e-04 6.49e-02f 1\n", - " 182r 0.0000000e+00 9.87e+03 6.42e+03 -9.0 7.25e-03 3.1 5.46e-01 1.00e-01f 1\n", - " 183r 0.0000000e+00 9.73e+03 6.33e+03 -9.0 6.49e-03 3.6 1.80e-03 1.41e-02f 1\n", - " 184r 0.0000000e+00 9.62e+03 6.26e+03 -9.0 6.50e-03 3.1 4.24e-02 1.10e-02f 1\n", - " 185r 0.0000000e+00 7.00e+03 4.55e+03 -9.0 6.45e-03 2.6 3.60e-04 2.73e-01f 1\n", - " 186r 0.0000000e+00 6.97e+03 4.53e+03 -9.0 5.09e-03 3.0 1.18e-03 3.67e-03f 1\n", - " 187r 0.0000000e+00 6.93e+03 4.50e+03 -9.0 4.62e-03 3.5 9.12e-03 5.95e-03f 1\n", - " 188r 0.0000000e+00 6.88e+03 4.47e+03 -9.0 9.78e-03 3.0 2.63e-03 7.75e-03f 1\n", - " 189r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 4.56e-03 3.4 1.08e-02 1.03e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 190r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 1.24e-02 2.9 1.78e-03 1.61e-04h 1\n", - " 191r 0.0000000e+00 6.15e+03 4.01e+03 -9.0 8.77e-03 2.5 2.48e-01 3.54e-05h 1\n", - " 192r 0.0000000e+00 6.14e+03 4.00e+03 -9.0 4.47e-02 2.0 6.49e-03 2.12e-03f 1\n", - " 193r 0.0000000e+00 6.13e+03 3.99e+03 -9.0 4.89e-03 2.4 3.55e-01 1.55e-03f 1\n", - " 194r 0.0000000e+00 6.02e+03 3.92e+03 -9.0 7.16e-03 1.9 7.71e-01 1.91e-02f 1\n", - " 195r 0.0000000e+00 5.16e+03 3.36e+03 -9.0 4.03e-03 2.4 9.96e-01 1.42e-01f 1\n", - " 196r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 1.87e-02 1.9 5.20e-04 2.15e-01f 1\n", - " 197r 0.0000000e+00 4.55e+03 2.64e+03 -9.0 4.46e-03 2.3 4.29e-03 5.76e-04h 1\n", - " 198r 0.0000000e+00 4.51e+03 2.61e+03 -9.0 6.37e-03 1.8 8.65e-02 8.50e-03f 1\n", - " 199r 0.0000000e+00 3.82e+03 2.24e+03 -9.0 9.97e-03 1.3 1.00e+00 1.43e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 200r 0.0000000e+00 2.28e+04 1.11e+03 -9.0 2.99e-02 0.9 1.00e+00 6.04e-01f 1\n", - " 201r 0.0000000e+00 2.26e+04 1.11e+03 -9.0 8.97e-02 0.4 2.64e-05 9.38e-03h 1\n", - " 202r 0.0000000e+00 2.25e+04 1.19e+03 -9.0 2.69e-01 -0.1 1.56e-02 3.25e-03h 1\n", - " 203r 0.0000000e+00 2.15e+04 2.29e+03 -9.0 1.01e-01 0.3 5.21e-03 1.31e-01f 1\n", - " 204r 0.0000000e+00 2.11e+04 2.25e+03 -9.0 8.35e-04 2.6 1.00e+00 1.69e-02h 1\n", - " 205r 0.0000000e+00 1.69e+04 1.84e+03 -9.0 1.81e-03 2.1 2.01e-02 1.92e-01f 1\n", - " 206r 0.0000000e+00 1.10e+04 1.29e+03 -9.0 5.32e-03 1.6 6.72e-03 2.90e-01f 1\n", - " 207r 0.0000000e+00 1.05e+04 1.25e+03 -9.0 1.60e-02 1.1 7.06e-03 3.85e-02h 1\n", - " 208r 0.0000000e+00 9.50e+03 1.49e+03 -9.0 4.79e-02 0.7 3.24e-01 4.74e-02h 1\n", - " 209r 0.0000000e+00 8.97e+03 1.26e+03 -9.0 9.53e-04 2.9 1.95e-01 5.50e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 210r 0.0000000e+00 7.49e+03 1.11e+03 -9.0 8.42e-04 2.4 8.89e-03 1.56e-01f 1\n", - " 211r 0.0000000e+00 6.41e+03 1.03e+03 -9.0 2.53e-03 1.9 2.59e-01 1.10e-01h 1\n", - " 212r 0.0000000e+00 6.25e+03 9.97e+02 -9.0 9.47e-04 2.4 1.55e-01 2.46e-02h 1\n", - " 213r 0.0000000e+00 6.20e+03 1.02e+03 -9.0 2.84e-03 1.9 3.65e-02 8.08e-03h 1\n", - " 214r 0.0000000e+00 5.92e+03 9.77e+02 -9.0 1.07e-03 2.3 6.08e-02 4.16e-02h 1\n", - " 215r 0.0000000e+00 2.22e+03 7.30e+02 -9.0 3.20e-03 1.8 1.25e-01 3.00e-01f 1\n", - " 216r 0.0000000e+00 1.94e+03 6.47e+02 -9.0 1.20e-03 2.3 9.91e-02 1.06e-01f 1\n", - " 217r 0.0000000e+00 6.72e+02 5.25e+02 -9.0 4.50e-04 2.7 1.64e-02 6.72e-01f 1\n", - " 218r 0.0000000e+00 5.81e+02 4.55e+02 -9.0 1.35e-03 2.2 9.70e-03 8.26e-02f 1\n", - " 219r 0.0000000e+00 5.71e+02 1.45e+03 -9.0 4.05e-03 1.7 4.53e-01 1.86e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 220r 0.0000000e+00 2.88e+02 3.97e+02 -9.0 1.21e-02 1.3 8.93e-01 4.98e-01h 1\n", - " 221r 0.0000000e+00 2.84e+02 3.68e+02 -9.0 3.64e-02 0.8 3.94e-01 1.41e-02h 1\n", - " 222r 0.0000000e+00 2.60e+02 3.31e+02 -9.0 1.09e-01 0.3 2.98e-01 8.74e-02h 1\n", - " 223r 0.0000000e+00 2.58e+02 2.99e+02 -9.0 9.90e-03 1.6 7.50e-04 1.48e-02h 1\n", - " 224r 0.0000000e+00 2.57e+02 6.28e+02 -9.0 1.92e-03 2.1 2.26e-01 1.81e-03h 1\n", - " 225r 0.0000000e+00 2.57e+02 3.39e+02 -9.0 6.80e-02 2.5 1.38e-03 2.43e-05h 1\n", - " 226r 0.0000000e+00 1.79e+02 5.12e+02 -9.0 2.16e-03 2.0 6.20e-01 1.47e-01f 1\n", - " 227r 0.0000000e+00 1.77e+02 5.05e+02 -9.0 6.48e-03 1.5 2.81e-01 1.03e-02h 1\n", - " 228r 0.0000000e+00 1.65e+02 3.97e+02 -9.0 1.94e-02 1.1 2.14e-01 6.66e-02f 1\n", - " 229r 0.0000000e+00 1.53e+02 2.65e+02 -9.0 5.83e-02 0.6 2.73e-01 7.17e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 230r 0.0000000e+00 1.42e+02 2.46e+02 -9.0 1.75e-01 0.1 8.87e-02 8.18e-02h 1\n", - " 231r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 1.28e+05 - 5.16e-05 3.99e-07f 1\n", - " 232r 0.0000000e+00 1.42e+02 4.93e+02 -9.0 5.25e-01 -0.4 1.92e-06 1.34e-06h 1\n", - " 233r 0.0000000e+00 1.42e+02 4.45e+02 -9.0 1.57e+00 -0.8 3.69e-03 7.18e-04f 1\n", - " 234r 0.0000000e+00 1.42e+02 5.41e+02 -9.0 2.69e+05 - 1.52e-04 3.85e-08f 1\n", - " 235r 0.0000000e+00 1.35e+02 4.90e+02 -9.0 4.69e+00 -1.3 2.20e-02 4.92e-02f 1\n", - " 236r 0.0000000e+00 1.34e+02 1.04e+03 -9.0 5.20e+00 -1.8 1.65e-01 8.17e-03f 1\n", - " 237r 0.0000000e+00 1.34e+02 1.46e+03 -9.0 2.44e-01 -0.5 4.95e-03 6.83e-04h 1\n", - " 238r 0.0000000e+00 1.33e+02 1.34e+03 -9.0 7.33e-01 -1.0 8.65e-02 2.12e-03f 1\n", - " 239r 0.0000000e+00 1.30e+02 1.67e+03 -9.0 2.20e+00 -1.4 1.00e+00 2.18e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 240r 0.0000000e+00 1.50e+01 2.99e+02 -9.0 3.35e-02 -1.9 5.05e-01 8.07e-01h 1\n", - " 241r 0.0000000e+00 1.41e+01 3.16e+02 -9.0 1.15e-01 -2.4 1.15e-01 5.72e-02h 1\n", - " 242r 0.0000000e+00 1.41e+01 2.96e+02 -9.0 2.21e-01 -2.9 8.95e-01 1.86e-04h 1\n", - " 243r 0.0000000e+00 1.36e+01 9.56e+02 -9.0 3.57e-01 -3.3 1.00e+00 3.35e-02f 1\n", - " 244r 0.0000000e+00 1.78e+01 7.29e+02 -9.0 4.00e-01 -3.8 1.00e+00 4.13e-01h 1\n", - " 245r 0.0000000e+00 2.17e+01 2.28e+02 -9.0 4.79e-02 - 1.00e+00 6.97e-01f 1\n", - " 246r 0.0000000e+00 3.53e-01 7.74e+00 -9.0 3.37e-02 - 1.00e+00 9.87e-01h 1\n", - " 247r 0.0000000e+00 2.49e-05 1.14e-04 -9.0 7.44e-06 - 1.00e+00 1.00e+00h 1\n", + " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", + " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", + " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", + " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", + " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", + " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", + " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", + " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", + " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 247\n", + "Number of Iterations....: 99\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 5.2592245504893751e-10 2.4923690943978723e-05\n", + "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", "\n", "\n", - "Number of objective function evaluations = 506\n", + "Number of objective function evaluations = 122\n", "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 507\n", + "Number of equality constraint evaluations = 123\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 250\n", + "Number of equality constraint Jacobian evaluations = 102\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 247\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.581\n", - "Total CPU secs in NLP function evaluations = 0.031\n", + "Number of Lagrangian Hessian evaluations = 99\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", "EXIT: Optimal Solution Found.\n" ] @@ -2199,8 +2036,8 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.337367Z", - "start_time": "2025-06-24T19:31:58.332051Z" + "end_time": "2025-06-26T20:17:07.732008Z", + "start_time": "2025-06-26T20:17:07.728387Z" } }, "source": [ @@ -2220,8 +2057,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.418255Z", - "start_time": "2025-06-24T19:31:58.357169Z" + "end_time": "2025-06-26T20:17:07.863289Z", + "start_time": "2025-06-26T20:17:07.761385Z" } }, "source": [ @@ -2239,7 +2076,7 @@ " Stream Table\n", " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4150e-07 8.4150e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", + " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", @@ -2265,8 +2102,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.432469Z", - "start_time": "2025-06-24T19:31:58.429050Z" + "end_time": "2025-06-26T20:17:07.883053Z", + "start_time": "2025-06-26T20:17:07.876775Z" } }, "source": [ @@ -2277,7 +2114,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 419122.33873277955\n" + "operating cost = $ 419122.3387221198\n" ] } ], @@ -2294,8 +2131,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.563246Z", - "start_time": "2025-06-24T19:31:58.542913Z" + "end_time": "2025-06-26T20:17:08.049906Z", + "start_time": "2025-06-26T20:17:08.024951Z" } }, "source": [ @@ -2336,7 +2173,7 @@ " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.824296294393142\n" + "benzene purity = 0.8242962943938487\n" ] } ], @@ -2353,8 +2190,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.605718Z", - "start_time": "2025-06-24T19:31:58.589778Z" + "end_time": "2025-06-26T20:17:08.106226Z", + "start_time": "2025-06-26T20:17:08.088181Z" } }, "source": [ @@ -2373,7 +2210,7 @@ "text": [ " Units Reactor Light Gases\n", "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4150e-07 1.0000e-08 \n", + "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", @@ -2420,8 +2257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.632091Z", - "start_time": "2025-06-24T19:31:58.629265Z" + "end_time": "2025-06-26T20:17:08.138832Z", + "start_time": "2025-06-26T20:17:08.135122Z" } }, "source": [ @@ -2441,8 +2278,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.663762Z", - "start_time": "2025-06-24T19:31:58.659017Z" + "end_time": "2025-06-26T20:17:08.178125Z", + "start_time": "2025-06-26T20:17:08.175210Z" } }, "source": [ @@ -2478,8 +2315,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.692331Z", - "start_time": "2025-06-24T19:31:58.689328Z" + "end_time": "2025-06-26T20:17:08.197104Z", + "start_time": "2025-06-26T20:17:08.193860Z" } }, "source": [ @@ -2495,8 +2332,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.721740Z", - "start_time": "2025-06-24T19:31:58.718213Z" + "end_time": "2025-06-26T20:17:08.224222Z", + "start_time": "2025-06-26T20:17:08.221218Z" } }, "source": [ @@ -2525,8 +2362,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.775901Z", - "start_time": "2025-06-24T19:31:58.772587Z" + "end_time": "2025-06-26T20:17:08.291933Z", + "start_time": "2025-06-26T20:17:08.289122Z" } }, "source": [ @@ -2559,8 +2396,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.811295Z", - "start_time": "2025-06-24T19:31:58.808287Z" + "end_time": "2025-06-26T20:17:08.321925Z", + "start_time": "2025-06-26T20:17:08.318981Z" } }, "source": [ @@ -2576,8 +2413,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.829624Z", - "start_time": "2025-06-24T19:31:58.825571Z" + "end_time": "2025-06-26T20:17:08.350491Z", + "start_time": "2025-06-26T20:17:08.346275Z" } }, "source": [ @@ -2599,8 +2436,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.844289Z", - "start_time": "2025-06-24T19:31:58.839950Z" + "end_time": "2025-06-26T20:17:08.380399Z", + "start_time": "2025-06-26T20:17:08.376824Z" } }, "source": [ @@ -2625,8 +2462,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.868128Z", - "start_time": "2025-06-24T19:31:58.863842Z" + "end_time": "2025-06-26T20:17:08.404523Z", + "start_time": "2025-06-26T20:17:08.401091Z" } }, "source": [ @@ -2661,8 +2498,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.891396Z", - "start_time": "2025-06-24T19:31:58.888249Z" + "end_time": "2025-06-26T20:17:08.434557Z", + "start_time": "2025-06-26T20:17:08.431016Z" } }, "source": [ @@ -2678,8 +2515,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-24T19:31:58.919132Z", - "start_time": "2025-06-24T19:31:58.916298Z" + "end_time": "2025-06-26T20:17:08.462910Z", + "start_time": "2025-06-26T20:17:08.459216Z" } }, "source": [ @@ -2702,8 +2539,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.013818Z", - "start_time": "2025-06-24T19:31:58.944881Z" + "end_time": "2025-06-26T20:17:08.495878Z", + "start_time": "2025-06-26T20:17:08.492876Z" } }, "source": [ @@ -2726,8 +2563,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.200536Z", - "start_time": "2025-06-24T19:31:59.023996Z" + "end_time": "2025-06-26T20:17:08.669116Z", + "start_time": "2025-06-26T20:17:08.518790Z" } }, "source": [ @@ -2743,9 +2580,9 @@ "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", "tol=1e-08\n", "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\n", + "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpxvrqimad_ipopt.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2800,74 +2637,55 @@ " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0401541e+05 1.21e+06 4.04e+16 -1.0 2.52e+04 - 1.00e+00 8.25e-04h 2\n", - " 17 3.0413501e+05 1.11e+06 3.40e+17 -1.0 2.52e+04 - 1.00e+00 8.05e-02h 2\n", - " 18 3.0413796e+05 1.11e+06 1.91e+19 -1.0 2.31e+04 - 2.08e-01 2.47e-04h 1\n", - " 19 3.0413716e+05 1.11e+06 3.11e+19 -1.0 2.31e+04 - 1.94e-01 6.23e-04h 1\n", + " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", + " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", + " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", + " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0412039e+05 1.11e+06 3.28e+20 -1.0 2.31e+04 - 6.31e-02 9.34e-04f 1\n", + " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0412039e+05 1.11e+06 1.00e+03 -0.5 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0411991e+05 1.10e+06 9.79e+03 -0.5 8.29e+03 - 4.94e-04 1.78e-03f 1\n", - " 23 3.0411969e+05 1.10e+06 2.08e+08 -1.0 2.63e+04 - 4.13e-01 2.94e-06f 2\n", - " 24 3.0412005e+05 1.10e+06 3.70e+12 -1.0 2.31e+04 - 9.90e-01 5.51e-05h 1\n", - " 25r 3.0412005e+05 1.10e+06 1.00e+03 -0.8 0.00e+00 - 0.00e+00 2.98e-07R 4\n", - " 26r 3.0412670e+05 1.07e+06 1.86e+04 -0.8 4.27e+03 - 3.64e-03 3.00e-03f 1\n", - " 27r 3.0413244e+05 1.02e+06 3.29e+04 -0.8 3.84e+03 - 5.44e-03 4.09e-03f 1\n", - " 28r 3.0414225e+05 9.31e+05 4.35e+04 -0.8 3.83e+03 - 1.10e-02 1.01e-02f 1\n", - " 29r 3.0415161e+05 7.83e+05 4.28e+04 -0.8 3.79e+03 - 3.09e-02 1.95e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 3.0415279e+05 4.89e+05 4.69e+04 -0.8 3.71e+03 - 6.61e-02 5.71e-02f 1\n", - " 31r 3.0413354e+05 2.21e+05 3.33e+04 -0.8 3.50e+03 - 2.36e-01 1.25e-01f 1\n", - " 32r 3.0412669e+05 1.70e+05 5.24e+04 -0.8 3.06e+03 - 3.06e-01 1.13e-01f 1\n", - " 33r 3.0410330e+05 3.57e+04 4.67e+04 -0.8 2.72e+03 - 1.13e-01 7.83e-01f 1\n", - " 34 3.0392384e+05 3.57e+04 9.72e+01 -1.0 4.10e+06 - 3.52e-04 3.56e-06f 1\n", - " 35 3.0389448e+05 3.57e+04 2.86e+03 -1.0 4.92e+05 - 1.02e-02 2.63e-04f 1\n", - " 36 3.0397678e+05 3.53e+04 2.73e+05 -1.0 2.87e+04 - 9.90e-01 1.03e-02h 1\n", - " 37 3.0835668e+05 7.78e+05 1.52e+05 -1.0 1.94e+04 - 1.00e+00 4.98e-01h 1\n", - " 38 3.1273940e+05 2.54e+05 4.38e+08 -1.0 9.74e+03 - 1.00e+00 9.90e-01h 1\n", - " 39 3.1276293e+05 1.32e+05 1.16e+08 -1.0 9.61e+02 - 1.00e+00 4.97e-01h 2\n", + " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", + " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", + " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", + " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", + " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", + " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", + " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", + " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40 3.1278677e+05 1.26e+02 1.07e+08 -1.0 4.99e+02 - 1.00e+00 9.99e-01H 1\n", - " 41 3.1278674e+05 2.93e+01 1.13e+05 -1.0 3.90e+01 - 1.00e+00 1.00e+00h 1\n", - " 42 3.1278674e+05 1.61e-05 6.30e-01 -1.0 3.33e-02 - 1.00e+00 1.00e+00h 1\n", - " 43 3.1278634e+05 3.48e-05 1.58e+05 -5.7 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 44 3.1278634e+05 1.49e-08 6.71e-02 -5.7 3.26e-05 - 1.00e+00 1.00e+00f 1\n", - " 45 3.1278634e+05 2.98e-08 4.40e-05 -5.7 1.43e-07 - 1.00e+00 1.00e+00h 1\n", - " 46 3.1278634e+05 1.49e-08 6.20e-05 -8.6 2.50e-05 - 1.00e+00 1.00e+00h 1\n", - " 47 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 48 3.1278634e+05 1.49e-08 4.40e-05 -9.0 4.23e-11 - 1.00e+00 1.00e+00h 1\n", - " 49 3.1278634e+05 1.49e-08 4.40e-05 -9.0 9.56e-11 - 1.00e+00 1.00e+00h 1\n", - "Scaling factors are invalid - setting them all to 1.\n", - "MA27BD returned iflag=-4 and requires more memory.\n", - " Increase liw from 21555 to 43110 and la from 24590 to 51336 and factorize again.\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.99e-11 - 1.00e+00 1.00e+00h 1\n", - " 51 3.1278634e+05 1.49e-08 4.40e-05 -9.0 3.71e-11 - 1.00e+00 1.00e+00h 1\n", - " 52 3.1278634e+05 9.67e-08 4.40e-05 -9.0 5.47e-11 - 1.00e+00 2.50e-01h 3\n", - " 53 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.20e-11 - 1.00e+00 1.00e+00s 22\n", + " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", + " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", + " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", + " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", + " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", + " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", + " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", + " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", + " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", + " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", "\n", - "Number of Iterations....: 53\n", + "Number of Iterations....: 39\n", "\n", " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066684e+05 3.1278633834066684e+05\n", - "Dual infeasibility......: 4.3988857412862944e-05 3.8344676702058576e-05\n", - "Constraint violation....: 2.0579515874459978e-11 2.9802322387695312e-08\n", - "Complementarity.........: 9.2191617461622116e-10 9.2191617461622116e-10\n", - "Overall NLP error.......: 1.6340396115112548e-08 3.8344676702058576e-05\n", + "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", + "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", + "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", + "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", + "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", "\n", "\n", - "Number of objective function evaluations = 105\n", - "Number of objective gradient evaluations = 47\n", - "Number of equality constraint evaluations = 105\n", - "Number of inequality constraint evaluations = 105\n", - "Number of equality constraint Jacobian evaluations = 56\n", - "Number of inequality constraint Jacobian evaluations = 56\n", - "Number of Lagrangian Hessian evaluations = 54\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.093\n", - "Total CPU secs in NLP function evaluations = 0.004\n", + "Number of objective function evaluations = 62\n", + "Number of objective gradient evaluations = 39\n", + "Number of equality constraint evaluations = 62\n", + "Number of inequality constraint evaluations = 62\n", + "Number of equality constraint Jacobian evaluations = 40\n", + "Number of inequality constraint Jacobian evaluations = 40\n", + "Number of Lagrangian Hessian evaluations = 39\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", + "Total CPU secs in NLP function evaluations = 0.008\n", "\n", - "EXIT: Solved To Acceptable Level.\n" + "EXIT: Optimal Solution Found.\n" ] } ], @@ -2886,8 +2704,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.272458Z", - "start_time": "2025-06-24T19:31:59.235423Z" + "end_time": "2025-06-26T20:17:08.738912Z", + "start_time": "2025-06-26T20:17:08.700529Z" } }, "source": [ @@ -2910,7 +2728,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 312786.3383406669\n", + "operating cost = $ 312786.3383406665\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -2940,7 +2758,7 @@ " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188276578115892\n", + "benzene purity = 0.8188276578115862\n", "\n", "Overhead loss in F101\n", "\n", @@ -2985,8 +2803,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-24T19:31:59.312310Z", - "start_time": "2025-06-24T19:31:59.308432Z" + "end_time": "2025-06-26T20:17:08.793956Z", + "start_time": "2025-06-26T20:17:08.789446Z" } }, "source": [ From 2df2238cbe410a686256cb745cfc9efae58623be Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Mon, 25 Aug 2025 10:13:29 -0600 Subject: [PATCH 34/36] Created config files to implement modular properties framework and initialized the HDA flowsheet files to work with the modular properties framework. Currently not working due to unit model initialization error. --- .../mod/hda/hda_ideal_VLE_modular.py | 252 +++ .../mod/hda/hda_reaction_modular.py | 91 + .../docs/tut/core/hda_flowsheet.ipynb | 1459 +++-------------- .../notebooks/docs/tut/core/hda_flowsheet.py | 553 +++++++ 4 files changed, 1160 insertions(+), 1195 deletions(-) create mode 100644 idaes_examples/mod/hda/hda_ideal_VLE_modular.py create mode 100644 idaes_examples/mod/hda/hda_reaction_modular.py create mode 100644 idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py diff --git a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py new file mode 100644 index 00000000..7aaf9f76 --- /dev/null +++ b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py @@ -0,0 +1,252 @@ +################################################################################# +# The Institute for the Design of Advanced Energy Systems Integrated Platform +# Framework (IDAES IP) was produced under the DOE Institute for the +# Design of Advanced Energy Systems (IDAES). +# +# Copyright (c) 2018-2024 by the software owners: The Regents of the +# University of California, through Lawrence Berkeley National Laboratory, +# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon +# University, West Virginia University Research Corporation, et al. +# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md +# for full copyright and license information. +################################################################################# +""" +Benzene-Toluene phase equilibrium package using ideal liquid and vapor. + +Example property package using the Generic Property Package Framework. +This exmample shows how to set up a property package to do benzene-toluene +phase equilibrium in the generic framework using ideal liquid and vapor +assumptions along with methods drawn from the pre-built IDAES property +libraries. +""" +# Import Pyomo units +from pyomo.environ import units as pyunits + +# Import IDAES cores +from idaes.core import LiquidPhase, VaporPhase, Component +import idaes.logger as idaeslog + +from idaes.models.properties.modular_properties.state_definitions import FpcTP +from idaes.models.properties.modular_properties.eos.ideal import Ideal +from idaes.models.properties.modular_properties.phase_equil import SmoothVLE +from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( + IdealBubbleDew, +) +from idaes.models.properties.modular_properties.phase_equil.forms import fugacity +from idaes.models.properties.modular_properties.pure import Perrys +from idaes.models.properties.modular_properties.pure import RPP5 + +# Set up logger +_log = idaeslog.getLogger(__name__) + +# --------------------------------------------------------------------- +# Configuration dictionary for an ideal Benzene-Toluene system + +# Data Sources: +# [1] The Properties of Gases and Liquids (1987) +# 4th edition, Chemical Engineering Series - Robert C. Reid +# [2] Perry's Chemical Engineers' Handbook 7th Ed. +# [3] Engineering Toolbox, https://www.engineeringtoolbox.com +# Retrieved 1st December, 2019 + +thermo_config = { + # Specifying components + "components": { + "benzene": { + "type": Component, + "elemental_composition": {"C": 6, "H": 6}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (78.1136e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (48.9e5, pyunits.Pa), # [1] + "temperature_crit": (562.2, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (1.0162, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.2655, None), + "3": (562.16, pyunits.K), + "4": (0.28212, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (-3.392e1, None), # [1] + "a1": (4.739e-1, pyunits.K**-1), + "a2": (-3.017e-4, pyunits.K**-2), + "a3": (7.130e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (1.29e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.7e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (6.48e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (49.0e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (82.9e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (4.202, pyunits.dimensionless), # [1] + "B": (1322, pyunits.K), + "C": (-38.56, pyunits.K), + }, + }, + }, + "toluene": { + "type": Component, + "elemental_composition": {"C": 7, "H": 8}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (92.1405e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (41e5, pyunits.Pa), # [1] + "temperature_crit": (591.8, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (0.8488, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.26655, None), + "3": (591.8, pyunits.K), + "4": (0.2878, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (-2.435e1, None), # [1] + "a1": (5.125e-1, pyunits.K**-1), + "a2": (-2.765e-4, pyunits.K**-2), + "a3": (4.911e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (1.40e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.52e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (6.95e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (12.0e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (50.1e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (4.216, pyunits.dimensionless), # [1] + "B": (1435, pyunits.K), + "C": (-43.33, pyunits.K), + }, + }, + }, + "hydrogen": { + "type": Component, + "elemental_composition": {"H": 2}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (2.016e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (12.9e5, pyunits.Pa), # [1] + "temperature_crit": (33.0, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (5.414, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.34893, None), + "3": (33.19, pyunits.K), + "4": (0.2706, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (2.714e1, None), # [1] + "a1": (9.274e-3, pyunits.K**-1), + "a2": (-1.381e-5, pyunits.K**-2), + "a3": (7.645e-9, pyunits.K**-3), + "a4": (0.0, pyunits.K ** -4), + }, + "cp_mol_liq_comp_coeff": { + "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (3.543, pyunits.dimensionless), # [1] + "B": (99.40, pyunits.K), + "C": (7.726, pyunits.K), + }, + }, + }, + "methane": { + "type": Component, + "elemental_composition": {"C": 1, "H": 4}, + "dens_mol_liq_comp": Perrys, + "enth_mol_liq_comp": Perrys, + "enth_mol_ig_comp": RPP5, + "pressure_sat_comp": RPP5, + "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, + "parameter_data": { + "mw": (16.043e-3, pyunits.kg / pyunits.mol), # [1] + "pressure_crit": (4.599e6, pyunits.Pa), # [1] + "temperature_crit": (190.564, pyunits.K), # [1] + "dens_mol_liq_comp_coeff": { + "eqn_type": 1, + "1": (2.9214, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "2": (0.28976, None), + "3": (190.56, pyunits.K), + "4": (0.28881, None), + }, + "cp_mol_ig_comp_coeff": { + "a0": (1.925e1, None), # [1] + "a1": (5.213e-2, pyunits.K**-1), + "a2": (1.197e-5, pyunits.K**-2), + "a3": (-1.132e-8, pyunits.K**-3), + "a4": (0.0, pyunits.K**-4), + }, + "cp_mol_liq_comp_coeff": { + "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + }, + "enth_mol_form_liq_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + "pressure_sat_comp_coeff": { + "A": (3.990, pyunits.dimensionless), # [1] + "B": (443.0, pyunits.K), + "C": (-0.49, pyunits.K), + }, + }, + }, + + }, + # Specifying phases + "phases": { + "Liq": {"type": LiquidPhase, "equation_of_state": Ideal}, + "Vap": {"type": VaporPhase, "equation_of_state": Ideal}, + }, + # + # # Set base units of measurement + "base_units": { + "time": pyunits.s, + "length": pyunits.m, + "mass": pyunits.kg, + "amount": pyunits.mol, + "temperature": pyunits.K, + }, + # # Specifying state definition + "state_definition": FpcTP, + "state_bounds": { + "flow_mol_phase_comp": (1e-12, .5, 100, pyunits.mol / pyunits.s), + "temperature": (298, 298.15, 1000, pyunits.K), + "pressure": (100000, 101325, 1000000, pyunits.Pa), + }, + "pressure_ref": (101325, pyunits.Pa), + "temperature_ref": (298.15, pyunits.K), + # Defining phase equilibria + "phases_in_equilibrium": [("Vap", "Liq")], + "phase_equilibrium_state": {("Vap", "Liq"): SmoothVLE}, + "bubble_dew_method": IdealBubbleDew, +} diff --git a/idaes_examples/mod/hda/hda_reaction_modular.py b/idaes_examples/mod/hda/hda_reaction_modular.py new file mode 100644 index 00000000..831c8684 --- /dev/null +++ b/idaes_examples/mod/hda/hda_reaction_modular.py @@ -0,0 +1,91 @@ +################################################################################# +# The Institute for the Design of Advanced Energy Systems Integrated Platform +# Framework (IDAES IP) was produced under the DOE Institute for the +# Design of Advanced Energy Systems (IDAES). +# +# Copyright (c) 2018-2024 by the software owners: The Regents of the +# University of California, through Lawrence Berkeley National Laboratory, +# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon +# University, West Virginia University Research Corporation, et al. +# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md +# for full copyright and license information. +################################################################################# +""" +Benzene-Toluene phase equilibrium package using ideal liquid and vapor. + +Example property package using the Generic Property Package Framework. +This exmample shows how to set up a property package to do benzene-toluene +phase equilibrium in the generic framework using ideal liquid and vapor +assumptions along with methods drawn from the pre-built IDAES property +libraries. +""" +# Import Pyomo units +from pyomo.environ import units as pyunits + +# Import IDAES cores +from idaes.core import LiquidPhase, VaporPhase, Component +import idaes.logger as idaeslog + +from idaes.models.properties.modular_properties.state_definitions import FTPx +from idaes.models.properties.modular_properties.eos.ideal import Ideal +from idaes.models.properties.modular_properties.phase_equil import SmoothVLE +from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( + IdealBubbleDew, +) +from idaes.models.properties.modular_properties.phase_equil.forms import fugacity +from idaes.models.properties.modular_properties.pure import Perrys +from idaes.models.properties.modular_properties.pure import RPP5 +from idaes.models.properties.modular_properties.reactions.rate_forms import power_law_rate +from idaes.models.properties.modular_properties.reactions.dh_rxn import constant_dh_rxn +from idaes.models.properties.modular_properties.reactions.rate_constant import arrhenius +from idaes.models.properties.modular_properties.base.utility import ConcentrationForm + +# Set up logger +_log = idaeslog.getLogger(__name__) + +# --------------------------------------------------------------------- +# Configuration dictionary for an ideal Benzene-Toluene system + +# Data Sources: +# [1] The Properties of Gases and Liquids (1987) +# 4th edition, Chemical Engineering Series - Robert C. Reid +# [2] Perry's Chemical Engineers' Handbook 7th Ed. +# [3] Engineering Toolbox, https://www.engineeringtoolbox.com +# Retrieved 1st December, 2019 + +reaction_config = { + + 'rate_reactions': { + "hydrodealkylation": { + "stoichiometry": { + ("Vap", "benzene"): 1, + ("Vap", "toluene"): -1, + ("Vap", "hydrogen"): -1, + ("Vap", "methane"): 1, + }, + "heat_of_reaction": constant_dh_rxn, + "rate_constant": arrhenius, + "rate_form": power_law_rate, + "concentration_form": ConcentrationForm.partialPressure, + "parameter_data": { + "dh_rxn_ref": (-1.08e5, pyunits.J / pyunits.mol), + "arrhenius_const": (6.3e10, pyunits.mol * pyunits.m ** -3 * pyunits.s ** -1 * pyunits.Pa ** -1.5), + "energy_activation": (217.6e3, pyunits.J / pyunits.mol), + "reaction_order": { + ("Vap", "benzene"): 0, + ("Vap", "toluene"): 1.0, + ("Vap", "hydrogen"): .5, + ("Vap", "methane"): 0, } + } + } + }, + + # Set base units of measurement + "base_units": { + "time": pyunits.s, + "length": pyunits.m, + "mass": pyunits.kg, + "amount": pyunits.mol, + "temperature": pyunits.K, + }, +} diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index 58481dd5..a9654d09 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" + "end_time": "2025-07-15T22:29:16.862036Z", + "start_time": "2025-07-15T22:29:16.858494Z" } }, "source": [ @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" + "end_time": "2025-07-15T22:29:17.440971Z", + "start_time": "2025-07-15T22:29:17.070381Z" } }, "source": [ @@ -160,8 +160,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" + "end_time": "2025-07-15T22:29:18.862462Z", + "start_time": "2025-07-15T22:29:17.454785Z" } }, "source": [ @@ -174,8 +174,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" + "end_time": "2025-07-15T22:29:18.975963Z", + "start_time": "2025-07-15T22:29:18.870712Z" } }, "source": [ @@ -212,8 +212,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" + "end_time": "2025-07-15T22:29:18.986206Z", + "start_time": "2025-07-15T22:29:18.983178Z" } }, "source": [ @@ -229,8 +229,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" + "end_time": "2025-07-15T22:29:19.000804Z", + "start_time": "2025-07-15T22:29:18.997523Z" } }, "source": [ @@ -251,8 +251,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" + "end_time": "2025-07-15T22:29:19.013373Z", + "start_time": "2025-07-15T22:29:19.010633Z" } }, "source": [ @@ -291,8 +291,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" + "end_time": "2025-07-15T22:29:19.029237Z", + "start_time": "2025-07-15T22:29:19.021824Z" } }, "source": [ @@ -302,6 +302,27 @@ "outputs": [], "execution_count": 8 }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-15T22:29:19.117688Z", + "start_time": "2025-07-15T22:29:19.037801Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 9 + }, { "cell_type": "markdown", "metadata": {}, @@ -315,8 +336,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" + "end_time": "2025-07-15T22:29:19.131934Z", + "start_time": "2025-07-15T22:29:19.127335Z" } }, "source": [ @@ -324,7 +345,7 @@ "m.fs = FlowsheetBlock(dynamic=False)" ], "outputs": [], - "execution_count": 9 + "execution_count": 10 }, { "cell_type": "markdown", @@ -337,18 +358,68 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" + "end_time": "2025-07-15T22:29:20.186702Z", + "start_time": "2025-07-15T22:29:19.143102Z" } }, "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" + "# m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", + "# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", + "# property_package=m.fs.thermo_params\n", + "# )\n", + "\n", + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)" ], - "outputs": [], - "execution_count": 10 + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2025-07-15 16:29:19 [ERROR] idaes.core.base.process_block: Failure in build: fs.thermo_params\n", + "Traceback (most recent call last):\n", + " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py\", line 41, in _rule_default\n", + " b.build()\n", + " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py\", line 470, in build\n", + " for p in self.phase_list:\n", + " ^^^^^^^^^^^^^^^\n", + " File \"C:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py\", line 550, in __getattr__\n", + " raise AttributeError(\n", + "AttributeError: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'\n", + "ERROR: Constructing component 'fs.thermo_params' from data=None failed:\n", + " AttributeError: '_ScalarGenericParameterBlock' object has no attribute\n", + " 'phase_list'\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'_ScalarGenericParameterBlock' object has no attribute 'phase_list'", + "output_type": "error", + "traceback": [ + "\u001B[31m---------------------------------------------------------------------------\u001B[39m", + "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)", + "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[11]\u001B[39m\u001B[32m, line 6\u001B[39m\n\u001B[32m 1\u001B[39m \u001B[38;5;66;03m# m.fs.thermo_params = thermo_props.HDAParameterBlock()\u001B[39;00m\n\u001B[32m 2\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\u001B[39;00m\n\u001B[32m 3\u001B[39m \u001B[38;5;66;03m# property_package=m.fs.thermo_params\u001B[39;00m\n\u001B[32m 4\u001B[39m \u001B[38;5;66;03m# )\u001B[39;00m\n\u001B[32m----> \u001B[39m\u001B[32m6\u001B[39m \u001B[43mm\u001B[49m\u001B[43m.\u001B[49m\u001B[43mfs\u001B[49m\u001B[43m.\u001B[49m\u001B[43mthermo_params\u001B[49m = GenericParameterBlock(**thermo_config)\n\u001B[32m 7\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)\u001B[39;00m\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:571\u001B[39m, in \u001B[36mBlockData.__setattr__\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 566\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m name \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m.\u001B[34m__dict__\u001B[39m:\n\u001B[32m 567\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(val, Component):\n\u001B[32m 568\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 569\u001B[39m \u001B[38;5;66;03m# Pyomo components are added with the add_component method.\u001B[39;00m\n\u001B[32m 570\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m571\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43madd_component\u001B[49m\u001B[43m(\u001B[49m\u001B[43mname\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mval\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 572\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 573\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 574\u001B[39m \u001B[38;5;66;03m# Other Python objects are added with the standard __setattr__\u001B[39;00m\n\u001B[32m 575\u001B[39m \u001B[38;5;66;03m# method.\u001B[39;00m\n\u001B[32m 576\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 577\u001B[39m \u001B[38;5;28msuper\u001B[39m(BlockData, \u001B[38;5;28mself\u001B[39m).\u001B[34m__setattr__\u001B[39m(name, val)\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:1101\u001B[39m, in \u001B[36mBlockData.add_component\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 1093\u001B[39m logger.debug(\n\u001B[32m 1094\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mConstructing \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m on \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m from data=\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m\"\u001B[39m,\n\u001B[32m 1095\u001B[39m val.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m,\n\u001B[32m (...)\u001B[39m\u001B[32m 1098\u001B[39m \u001B[38;5;28mstr\u001B[39m(data),\n\u001B[32m 1099\u001B[39m )\n\u001B[32m 1100\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1101\u001B[39m \u001B[43mval\u001B[49m\u001B[43m.\u001B[49m\u001B[43mconstruct\u001B[49m\u001B[43m(\u001B[49m\u001B[43mdata\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1102\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m:\n\u001B[32m 1103\u001B[39m err = sys.exc_info()[\u001B[32m1\u001B[39m]\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2233\u001B[39m, in \u001B[36mBlock.construct\u001B[39m\u001B[34m(self, data)\u001B[39m\n\u001B[32m 2231\u001B[39m obj.construct(data.get(name, \u001B[38;5;28;01mNone\u001B[39;00m))\n\u001B[32m 2232\u001B[39m \u001B[38;5;66;03m# Trigger the (normal) initialization of the block\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m2233\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_getitem_when_not_present\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_idx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2234\u001B[39m \u001B[38;5;28;01mfinally\u001B[39;00m:\n\u001B[32m 2235\u001B[39m \u001B[38;5;66;03m# We must allow that id(self) may no longer be in\u001B[39;00m\n\u001B[32m 2236\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data, as _getitem_when_not_present will\u001B[39;00m\n\u001B[32m 2237\u001B[39m \u001B[38;5;66;03m# have already removed the entry for scalar blocks (as the\u001B[39;00m\n\u001B[32m 2238\u001B[39m \u001B[38;5;66;03m# BlockData and the Block component are the same object)\u001B[39;00m\n\u001B[32m 2239\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m data \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2148\u001B[39m, in \u001B[36mBlock._getitem_when_not_present\u001B[39m\u001B[34m(self, idx)\u001B[39m\n\u001B[32m 2145\u001B[39m data = \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[32m 2147\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m2148\u001B[39m obj = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_rule\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_block\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2149\u001B[39m \u001B[38;5;66;03m# If the user returns a block, transfer over everything\u001B[39;00m\n\u001B[32m 2150\u001B[39m \u001B[38;5;66;03m# they defined into the empty one we created. We do\u001B[39;00m\n\u001B[32m 2151\u001B[39m \u001B[38;5;66;03m# this inside the try block so that any abstract\u001B[39;00m\n\u001B[32m 2152\u001B[39m \u001B[38;5;66;03m# components declared by the rule have the opportunity\u001B[39;00m\n\u001B[32m 2153\u001B[39m \u001B[38;5;66;03m# to be initialized with data from\u001B[39;00m\n\u001B[32m 2154\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data as they are transferred over.\u001B[39;00m\n\u001B[32m 2155\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m obj \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m _block \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(obj, BlockData):\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\initializer.py:351\u001B[39m, in \u001B[36mIndexedCallInitializer.__call__\u001B[39m\u001B[34m(self, parent, idx)\u001B[39m\n\u001B[32m 349\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m._fcn(parent, *idx)\n\u001B[32m 350\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m--> \u001B[39m\u001B[32m351\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_fcn\u001B[49m\u001B[43m(\u001B[49m\u001B[43mparent\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n", + "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py:41\u001B[39m, in \u001B[36m_rule_default\u001B[39m\u001B[34m(b, *args)\u001B[39m\n\u001B[32m 35\u001B[39m \u001B[38;5;250m\u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 36\u001B[39m \u001B[33;03mDefault rule for ProcessBlock, which calls build(). A different rule can\u001B[39;00m\n\u001B[32m 37\u001B[39m \u001B[33;03mbe specified to add additional build steps, or to not call build at all\u001B[39;00m\n\u001B[32m 38\u001B[39m \u001B[33;03musing the normal rule argument to ProcessBlock init.\u001B[39;00m\n\u001B[32m 39\u001B[39m \u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 40\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m---> \u001B[39m\u001B[32m41\u001B[39m \u001B[43mb\u001B[49m\u001B[43m.\u001B[49m\u001B[43mbuild\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 42\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m:\n\u001B[32m 43\u001B[39m logging.getLogger(\u001B[34m__name__\u001B[39m).exception(\u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33mFailure in build: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mb\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m\"\u001B[39m)\n", + "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py:470\u001B[39m, in \u001B[36mGenericParameterData.build\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 468\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m._electrolyte:\n\u001B[32m 469\u001B[39m pc_set = []\n\u001B[32m--> \u001B[39m\u001B[32m470\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mphase_list\u001B[49m:\n\u001B[32m 471\u001B[39m pobj = \u001B[38;5;28mself\u001B[39m.get_phase(p)\n\u001B[32m 472\u001B[39m pc_list = \u001B[38;5;28mself\u001B[39m.get_phase(p).config.component_list\n", + "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:550\u001B[39m, in \u001B[36mBlockData.__getattr__\u001B[39m\u001B[34m(self, val)\u001B[39m\n\u001B[32m 547\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m _component_decorator(\u001B[38;5;28mself\u001B[39m, ModelComponentFactory.get_class(val))\n\u001B[32m 548\u001B[39m \u001B[38;5;66;03m# Since the base classes don't support getattr, we can just\u001B[39;00m\n\u001B[32m 549\u001B[39m \u001B[38;5;66;03m# throw the \"normal\" AttributeError\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m550\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mAttributeError\u001B[39;00m(\n\u001B[32m 551\u001B[39m \u001B[33m\"\u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m object has no attribute \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m\"\u001B[39m % (\u001B[38;5;28mself\u001B[39m.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m, val)\n\u001B[32m 552\u001B[39m )\n", + "\u001B[31mAttributeError\u001B[39m: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'" + ] + } + ], + "execution_count": 11 }, { "cell_type": "markdown", @@ -361,12 +432,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, + "metadata": {}, "source": [ "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", @@ -384,7 +450,7 @@ ")" ], "outputs": [], - "execution_count": 11 + "execution_count": null }, { "cell_type": "markdown", @@ -412,28 +478,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } + ] }, "source": [ "# Todo: Add reactor with the specifications above" ], "outputs": [], - "execution_count": 12 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } + ] }, "source": [ "# Todo: Add reactor with the specifications above\n", @@ -446,7 +504,7 @@ ")" ], "outputs": [], - "execution_count": 13 + "execution_count": null }, { "cell_type": "markdown", @@ -462,12 +520,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", @@ -476,7 +529,7 @@ ")" ], "outputs": [], - "execution_count": 14 + "execution_count": null }, { "cell_type": "markdown", @@ -487,12 +540,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, + "metadata": {}, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -514,7 +562,7 @@ ")" ], "outputs": [], - "execution_count": 15 + "execution_count": null }, { "cell_type": "markdown", @@ -525,12 +573,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, + "metadata": {}, "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -539,7 +582,7 @@ "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], - "execution_count": 16 + "execution_count": null }, { "cell_type": "markdown", @@ -559,19 +602,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, + "metadata": {}, "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" ], "outputs": [], - "execution_count": 17 + "execution_count": null }, { "cell_type": "markdown", @@ -592,35 +630,27 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } + ] }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet" ], "outputs": [], - "execution_count": 18 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } + ] }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" ], "outputs": [], - "execution_count": 19 + "execution_count": null }, { "cell_type": "markdown", @@ -631,12 +661,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, + "metadata": {}, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", @@ -645,7 +670,7 @@ "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], - "execution_count": 20 + "execution_count": null }, { "cell_type": "markdown", @@ -656,19 +681,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, + "metadata": {}, "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" ], "outputs": [], - "execution_count": 21 + "execution_count": null }, { "cell_type": "markdown", @@ -679,17 +699,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, + "metadata": {}, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" ], "outputs": [], - "execution_count": 22 + "execution_count": null }, { "cell_type": "markdown", @@ -711,12 +726,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, + "metadata": {}, "source": [ "m.fs.purity = Expression(\n", " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -727,7 +737,7 @@ ")" ], "outputs": [], - "execution_count": 23 + "execution_count": null }, { "cell_type": "markdown", @@ -738,19 +748,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, + "metadata": {}, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" ], "outputs": [], - "execution_count": 24 + "execution_count": null }, { "cell_type": "markdown", @@ -767,19 +772,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, + "metadata": {}, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" ], "outputs": [], - "execution_count": 25 + "execution_count": null }, { "cell_type": "markdown", @@ -790,19 +790,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, + "metadata": {}, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" ], "outputs": [], - "execution_count": 26 + "execution_count": null }, { "cell_type": "markdown", @@ -821,27 +816,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, + "metadata": {}, "source": [ "autoscaler = AutoScaler()\n", "autoscaler.scale_model(m)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -855,43 +836,26 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, + "metadata": {}, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.810084Z", - "start_time": "2025-06-26T20:17:04.786754Z" - } + ] }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" ], "outputs": [], - "execution_count": 29 + "execution_count": null }, { "cell_type": "markdown", @@ -902,12 +866,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, + "metadata": {}, "source": [ "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", @@ -921,7 +880,7 @@ "m.fs.I101.pressure.fix(350000)" ], "outputs": [], - "execution_count": 30 + "execution_count": null }, { "cell_type": "markdown", @@ -941,12 +900,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, + "metadata": {}, "source": [ "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", @@ -960,7 +914,7 @@ "m.fs.I102.pressure.fix(350000)" ], "outputs": [], - "execution_count": 31 + "execution_count": null }, { "cell_type": "markdown", @@ -973,17 +927,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature.fix(600)" ], "outputs": [], - "execution_count": 32 + "execution_count": null }, { "cell_type": "markdown", @@ -994,12 +943,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, + "metadata": {}, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", @@ -1015,7 +959,7 @@ "m.fs.R101.heat_duty.fix(0)" ], "outputs": [], - "execution_count": 33 + "execution_count": null }, { "cell_type": "markdown", @@ -1026,18 +970,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" ], "outputs": [], - "execution_count": 34 + "execution_count": null }, { "cell_type": "markdown", @@ -1064,35 +1003,27 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } + ] }, "source": [ "# Todo: Set conditions for Flash F102" ], "outputs": [], - "execution_count": 35 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } + ] }, "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" ], "outputs": [], - "execution_count": 36 + "execution_count": null }, { "cell_type": "markdown", @@ -1103,18 +1034,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, + "metadata": {}, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" ], "outputs": [], - "execution_count": 37 + "execution_count": null }, { "cell_type": "markdown", @@ -1137,71 +1063,47 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } + ] }, "source": [ "# Todo: print the degrees of freedom" ], "outputs": [], - "execution_count": 38 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } + ] }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.104838Z", - "start_time": "2025-06-26T20:17:05.080097Z" - } + ] }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ], "outputs": [], - "execution_count": 40 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } + ] }, "source": [], "outputs": [], @@ -1238,12 +1140,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, + "metadata": {}, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -1256,7 +1153,7 @@ "order = seq.calculation_order(G)" ], "outputs": [], - "execution_count": 41 + "execution_count": null }, { "cell_type": "markdown", @@ -1267,26 +1164,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, + "metadata": {}, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1298,31 +1182,14 @@ { "cell_type": "code", "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } + "scrolled": true }, "source": [ "for o in order:\n", " print(o[0].name)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1338,12 +1205,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, + "metadata": {}, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1364,7 +1226,7 @@ "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" ], "outputs": [], - "execution_count": 44 + "execution_count": null }, { "cell_type": "markdown", @@ -1375,12 +1237,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, + "metadata": {}, "source": [ "def function(unit):\n", " try:\n", @@ -1391,7 +1248,7 @@ " solver.solve(unit)" ], "outputs": [], - "execution_count": 45 + "execution_count": null }, { "cell_type": "markdown", @@ -1402,17 +1259,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, + "metadata": {}, "source": [ "# seq.run(m, function)" ], "outputs": [], - "execution_count": 46 + "execution_count": null }, { "cell_type": "markdown", @@ -1426,17 +1278,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, + "metadata": {}, "source": [ "from idaes.core.util.initialization import propagate_state" ], "outputs": [], - "execution_count": 47 + "execution_count": null }, { "cell_type": "markdown", @@ -1449,25 +1296,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, + "metadata": {}, "source": [ "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1478,27 +1312,14 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, + "metadata": {}, "source": [ "m.fs.s03_expanded.deactivate()\n", "\n", "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1509,12 +1330,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, + "metadata": {}, "source": [ "tear_guesses = {\n", " \"flow_mol_phase_comp\": {\n", @@ -1538,16 +1354,8 @@ "DOF_initial = degrees_of_freedom(m)\n", "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1558,12 +1366,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", @@ -1593,36 +1396,8 @@ ") # Establish connection between Second Flash Unit and Toluene Product\n", "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1633,12 +1408,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, + "metadata": {}, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1649,92 +1419,8 @@ "solver = get_solver(options=optarg)\n", "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1745,12 +1431,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, + "metadata": {}, "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1761,16 +1442,8 @@ " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", ")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -1790,12 +1463,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, + "metadata": {}, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1805,7 +1473,7 @@ "}" ], "outputs": [], - "execution_count": 54 + "execution_count": null }, { "cell_type": "markdown", @@ -1831,11 +1499,7 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } + ] }, "source": [ "# Create the solver object\n", @@ -1843,18 +1507,14 @@ "# Solve the model" ], "outputs": [], - "execution_count": 55 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } + ] }, "source": [ "# Create the solver object\n", @@ -1863,202 +1523,15 @@ "# Solve the model\n", "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.713878Z", - "start_time": "2025-06-26T20:17:07.711084Z" - } + ] }, "source": [ "# Check solver solve status\n", @@ -2067,7 +1540,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 57 + "execution_count": null }, { "cell_type": "markdown", @@ -2090,17 +1563,13 @@ "metadata": { "tags": [ "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } + ] }, "source": [ "# m.fs.visualize(\"HDA-Flowsheet\")" ], "outputs": [], - "execution_count": 58 + "execution_count": null }, { "cell_type": "markdown", @@ -2111,41 +1580,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, + "metadata": {}, "source": [ "m.fs.report()" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -2156,36 +1596,19 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, + "metadata": {}, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.014719Z", - "start_time": "2025-06-26T20:17:07.926032Z" - } + ] }, "source": [ "import pytest\n", @@ -2193,7 +1616,7 @@ "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" ], "outputs": [], - "execution_count": 61 + "execution_count": null }, { "cell_type": "markdown", @@ -2204,66 +1627,22 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, + "metadata": {}, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.063578Z", - "start_time": "2025-06-26T20:17:08.060157Z" - } + ] }, "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", @@ -2271,7 +1650,7 @@ "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" ], "outputs": [], - "execution_count": 63 + "execution_count": null }, { "cell_type": "markdown", @@ -2282,12 +1661,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, + "metadata": {}, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -2297,26 +1671,8 @@ "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -2349,17 +1705,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, + "metadata": {}, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" ], "outputs": [], - "execution_count": 65 + "execution_count": null }, { "cell_type": "markdown", @@ -2370,12 +1721,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", @@ -2383,7 +1729,7 @@ "m.fs.F102.vap_outlet.temperature.unfix()" ], "outputs": [], - "execution_count": 66 + "execution_count": null }, { "cell_type": "markdown", @@ -2407,52 +1753,40 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } + ] }, "source": [ "# Todo: Unfix deltaP for F102" ], "outputs": [], - "execution_count": 67 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } + ] }, "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" ], "outputs": [], - "execution_count": 68 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.275146Z", - "start_time": "2025-06-26T20:17:08.249526Z" - } + ] }, "source": [ "assert degrees_of_freedom(m) == 5" ], "outputs": [], - "execution_count": 69 + "execution_count": null }, { "cell_type": "markdown", @@ -2471,18 +1805,13 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, + "metadata": {}, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" ], "outputs": [], - "execution_count": 70 + "execution_count": null }, { "cell_type": "markdown", @@ -2505,28 +1834,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } + ] }, "source": [ "# Todo: Set the bounds for reactor outlet temperature" ], "outputs": [], - "execution_count": 71 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } + ] }, "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", @@ -2534,7 +1855,7 @@ "m.fs.R101.outlet.temperature[0].setub(800)" ], "outputs": [], - "execution_count": 72 + "execution_count": null }, { "cell_type": "markdown", @@ -2545,12 +1866,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, + "metadata": {}, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -2560,7 +1876,7 @@ "m.fs.F102.vap_outlet.pressure[0].setub(110000)" ], "outputs": [], - "execution_count": 73 + "execution_count": null }, { "cell_type": "markdown", @@ -2571,12 +1887,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, + "metadata": {}, "source": [ "m.fs.overhead_loss = Constraint(\n", " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", @@ -2584,7 +1895,7 @@ ")" ], "outputs": [], - "execution_count": 74 + "execution_count": null }, { "cell_type": "markdown", @@ -2607,28 +1918,20 @@ "metadata": { "tags": [ "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } + ] }, "source": [ "# Todo: Add minimum product flow constraint" ], "outputs": [], - "execution_count": 75 + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } + ] }, "source": [ "# Todo: Add minimum product flow constraint\n", @@ -2637,7 +1940,7 @@ ")" ], "outputs": [], - "execution_count": 76 + "execution_count": null }, { "cell_type": "markdown", @@ -2648,17 +1951,12 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, + "metadata": {}, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" ], "outputs": [], - "execution_count": 77 + "execution_count": null }, { "cell_type": "markdown", @@ -2672,146 +1970,19 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, + "metadata": {}, "source": [ "results = solver.solve(m, tee=True)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.683743Z", - "start_time": "2025-06-26T20:17:08.679403Z" - } + ] }, "source": [ "# Check for solver solve status\n", @@ -2820,7 +1991,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 79 + "execution_count": null }, { "cell_type": "markdown", @@ -2833,12 +2004,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, + "metadata": {}, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -2854,92 +2020,22 @@ "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.756874Z", - "start_time": "2025-06-26T20:17:08.753678Z" - } + ] }, "source": [ "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" ], "outputs": [], - "execution_count": 81 + "execution_count": null }, { "cell_type": "markdown", @@ -2950,12 +2046,7 @@ }, { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, + "metadata": {}, "source": [ "print(\n", " f\"\"\"Optimal Values:\n", @@ -2971,37 +2062,15 @@ "\"\"\"\n", ")" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.825473Z", - "start_time": "2025-06-26T20:17:08.820372Z" - } + ] }, "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", @@ -3011,7 +2080,7 @@ "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" ], "outputs": [], - "execution_count": 83 + "execution_count": null } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py new file mode 100644 index 00000000..39b56e2f --- /dev/null +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py @@ -0,0 +1,553 @@ + +from pyomo.environ import ( + Constraint, + Var, + ConcreteModel, + Expression, + Objective, + SolverFactory, + TransformationFactory, + value, +) +from pyomo.network import Arc, SequentialDecomposition + +from idaes.core import FlowsheetBlock + +from idaes.models.unit_models import ( + PressureChanger, + IsentropicPressureChangerInitializer, + Mixer, + MixerInitializer, + Separator as Splitter, + SeparatorInitializer, + Heater, + StoichiometricReactor, + Feed, + Product, +) + +# Todo: import flash model from idaes.models.unit_models + +# Todo: import flash model from idaes.models.unit_models +from idaes.models.unit_models import Flash + + +from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption +from idaes.core.util.model_statistics import degrees_of_freedom +from idaes.core.scaling.util import set_scaling_factor +from idaes.core.scaling.autoscaling import AutoScaler + + +import idaes.logger as idaeslog +from idaes.core.solvers import get_solver +from idaes.core.util.exceptions import InitializationError + +from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props +from idaes_examples.mod.hda import hda_reaction as reaction_props + +from idaes.models.properties.modular_properties.base.generic_property import ( + GenericParameterBlock, +) +from idaes.models.properties.modular_properties.base.generic_reaction import ( + GenericReactionParameterBlock, +) +from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config +from idaes_examples.mod.hda.hda_reaction_modular import reaction_config + + +m = ConcreteModel() +m.fs = FlowsheetBlock(dynamic=False) + +thermo_params_og = thermo_props.HDAParameterBlock() +reaction_params_og = reaction_props.HDAReactionParameterBlock(property_package=thermo_params_og) +thermo_params_new = GenericParameterBlock(**thermo_config) +reaction_params_new = GenericReactionParameterBlock(property_package=thermo_params_new, **reaction_config) + +# m.fs.thermo_params = thermo_params_og +# m.fs.reaction_params = reaction_params_og +m.fs.thermo_params = thermo_params_new +m.fs.reaction_params = reaction_params_new + +m.fs.I101 = Feed(property_package=m.fs.thermo_params) + +m.fs.I102 = Feed(property_package=m.fs.thermo_params) + +m.fs.M101 = Mixer( + property_package=m.fs.thermo_params, + num_inlets=3, +) + +m.fs.H101 = Heater( + property_package=m.fs.thermo_params, + has_pressure_change=False, + has_phase_equilibrium=True, +) + +m.fs.R101 = StoichiometricReactor( + property_package=m.fs.thermo_params, + reaction_package=m.fs.reaction_params, + has_heat_of_reaction=True, + has_heat_transfer=True, + has_pressure_change=False, +) + +m.fs.F101 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, +) + +m.fs.S101 = Splitter( + property_package=m.fs.thermo_params, + ideal_separation=False, + outlet_list=["purge", "recycle"], +) + + +m.fs.C101 = PressureChanger( + property_package=m.fs.thermo_params, + compressor=True, + thermodynamic_assumption=ThermodynamicAssumption.isothermal, +) + +m.fs.F102 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, +) + +m.fs.P101 = Product(property_package=m.fs.thermo_params) +m.fs.P102 = Product(property_package=m.fs.thermo_params) +m.fs.P103 = Product(property_package=m.fs.thermo_params) + +m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1) +m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2) +m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet) +m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet) +m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet) +m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet) +m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet) +m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet) +m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3) +m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet) +m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet) +m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet) + +TransformationFactory("network.expand_arcs").apply_to(m) + +m.fs.purity = Expression( + expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + / ( + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "toluene"] + ) +) + +m.fs.cooling_cost = Expression( + expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0]) +) + +m.fs.heating_cost = Expression( + expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0] +) + +m.fs.operating_cost = Expression( + expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) +) + +# autoscaler = AutoScaler() +# autoscaler.scale_model(m) + +print(degrees_of_freedom(m)) + +assert degrees_of_freedom(m) == 29 + +m.fs.I101.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Vap", "methane"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "toluene"].fix(0.30) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) +m.fs.I101.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I101.temperature.fix(303.2) +m.fs.I101.pressure.fix(350000) + +m.fs.I102.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(0.30) +m.fs.I102.flow_mol_phase_comp[0, "Vap", "methane"].fix(0.02) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "toluene"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) +m.fs.I102.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I102.temperature.fix(303.2) +m.fs.I102.pressure.fix(350000) + +m.fs.H101.outlet.temperature.fix(600) + +m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) + +m.fs.R101.conv_constraint = Constraint( + expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] + == (m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) + +m.fs.R101.conversion.fix(0.75) +m.fs.R101.heat_duty.fix(0) + +m.fs.F101.vap_outlet.temperature.fix(325.0) +m.fs.F101.deltaP.fix(0) + +m.fs.F102.vap_outlet.temperature.fix(375) +m.fs.F102.deltaP.fix(-200000) + +m.fs.S101.split_fraction[0, "purge"].fix(0.2) +m.fs.C101.outlet.pressure.fix(350000) + +from idaes.core.util.initialization import propagate_state + +print(f"The DOF is {degrees_of_freedom(m)} initially") +m.fs.s03_expanded.deactivate() +print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") +tear_guesses = { + "flow_mol_phase_comp": { + (0, "Liq", "benzene"): 1e-5, + (0, "Liq", "toluene"): 0.30, + (0, "Liq", "methane"): 1e-5, + (0, "Liq", "hydrogen"): 1e-5, + (0, "Vap", "benzene"): 1e-5, + (0, "Vap", "toluene"): 1e-5, + (0, "Vap", "methane"): 0.5, + (0, "Vap", "hydrogen"): 0.5, + }, + "temperature": {0: 303}, + "pressure": {0: 350000}, +} + +for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.s03.destination, k)[k1].fix(v1) + +DOF_initial = degrees_of_freedom(m) +# x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) +# x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) +# x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) +# x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) + +# p_sat_dewT_0 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['benzene']) +# p_sat_dewT_1 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['toluene']) +# p_sat_dewT_2 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['hydrogen']) +# p_sat_dewT_3 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['methane']) +# +# print(p_sat_dewT_0) +# print(p_sat_dewT_1) +# print(p_sat_dewT_2) +# print(p_sat_dewT_3) + + +# +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['benzene'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['toluene'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['hydrogen'])) +# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['methane'])) +# +# print(value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew['Vap', 'Liq'])) + +# P = value(m.fs.H101.control_volume.properties_out[0.0].pressure) +# +# print(P*(x_0/p_sat_dewT_0 + x_1/p_sat_dewT_1) - 1) + + +m.fs.H101.default_initializer().initialize(m.fs.H101, output_level=idaeslog.INFO_HIGH) # Initialize Heater +x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) +x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) +x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) +x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) + +T_dew = value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew) +T_bub = value(m.fs.H101.control_volume.properties_out[0.0].temperature_bubble) +P_dew = value(m.fs.H101.control_volume.properties_out[0.0].pressure_dew) +P_bub = value(m.fs.H101.control_volume.properties_out[0.0].pressure_bubble) + +m.fs.H101.default_initializer().initialize(m.fs.H101) +propagate_state(m.fs.s04) # Establish connection between Heater and Reactor +m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor +propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit +m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit +propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter +propagate_state(m.fs.s07) +m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter +propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor +m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor +propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer +m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet +propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer +m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet +propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer +m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer +propagate_state(m.fs.s03) # Establish connection between Mixer and Heater +m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit +propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product +propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product +propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product + + +optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 300, + "tol": 1e-8, +} +solver = get_solver(options=optarg) +results = solver.solve(m, tee=True) + + +for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.H101.inlet, k)[k1].unfix() + +m.fs.s03_expanded.activate() +print( + f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" +) +#%% md +# ## 6 Solving the Model +#%% md +# We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html +#%% +optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 1000, + "tol": 1e-8, +} +#%% md +#
+# Inline Exercise: +# Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following: +# +# solver = get_solver(solver_options=optarg)
+# results = solver.solve(m, tee=True) +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+# +#%% +# Create the solver object + +# Solve the model +#%% +# Create the solver object +solver = get_solver(solver_options=optarg) + +# Solve the model +results = solver.solve(m, tee=True) +#%% +# Check solver solve status +from pyomo.environ import TerminationCondition + +assert results.solver.termination_condition == TerminationCondition.optimal +#%% md +# ## 7 Analyze the results +# +# +# +#%% md +# If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window. +# +#%% +# m.fs.visualize("HDA-Flowsheet") +#%% md +# Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display. +#%% +m.fs.report() +#%% md +# What is the total operating cost? +#%% +print("operating cost = $", value(m.fs.operating_cost)) +#%% +import pytest + +assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3) +#%% md +# For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method. +#%% +m.fs.F102.report() + +print() +print("benzene purity = ", value(m.fs.purity)) +#%% +assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) +assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3) +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) +#%% md +# Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101. +#%% +from idaes.core.util.tables import ( + create_stream_table_dataframe, + stream_table_dataframe_to_string, +) + +st = create_stream_table_dataframe({"Reactor": m.fs.s05, "Light Gases": m.fs.s06}) +print(stream_table_dataframe_to_string(st)) +#%% md +# ## 8 Optimization +# +# +# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. +# +# Let us try to minimize this cost such that: +# - we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream +# - purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80% +# - restricting the benzene loss in F101 vapor outlet to less than 20% +# +# For this problem, our decision variables are as follows: +# - H101 outlet temperature +# - R101 cooling duty provided +# - F101 outlet temperature +# - F102 outlet temperature +# - F102 deltaP in the flash tank +# +#%% md +# Let us declare our objective function for this problem. +#%% +m.fs.objective = Objective(expr=m.fs.operating_cost) +#%% md +# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. +#%% +m.fs.H101.outlet.temperature.unfix() +m.fs.R101.heat_duty.unfix() +m.fs.F101.vap_outlet.temperature.unfix() +m.fs.F102.vap_outlet.temperature.unfix() +#%% md +#
+# Inline Exercise: +# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+# +# +#%% +# Todo: Unfix deltaP for F102 +#%% +# Todo: Unfix deltaP for F102 +m.fs.F102.deltaP.unfix() +#%% +assert degrees_of_freedom(m) == 5 +#%% md +# Next, we need to set bounds on these decision variables to values shown below: +# +# - H101 outlet temperature [500, 600] K +# - R101 outlet temperature [600, 800] K +# - F101 outlet temperature [298, 450] K +# - F102 outlet temperature [298, 450] K +# - F102 outlet pressure [105000, 110000] Pa +# +# Let us first set the variable bound for the H101 outlet temperature as shown below: +#%% +m.fs.H101.outlet.temperature[0].setlb(500) +m.fs.H101.outlet.temperature[0].setub(600) +#%% md +#
+# Inline Exercise: +# Now, set the variable bound for the R101 outlet temperature. +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+#%% +# Todo: Set the bounds for reactor outlet temperature +#%% +# Todo: Set the bounds for reactor outlet temperature +m.fs.R101.outlet.temperature[0].setlb(600) +m.fs.R101.outlet.temperature[0].setub(800) +#%% md +# Let us fix the bounds for the rest of the decision variables. +#%% +m.fs.F101.vap_outlet.temperature[0].setlb(298.0) +m.fs.F101.vap_outlet.temperature[0].setub(450.0) +m.fs.F102.vap_outlet.temperature[0].setlb(298.0) +m.fs.F102.vap_outlet.temperature[0].setub(450.0) +m.fs.F102.vap_outlet.pressure[0].setlb(105000) +m.fs.F102.vap_outlet.pressure[0].setub(110000) +#%% md +# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. +#%% +m.fs.overhead_loss = Constraint( + expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "benzene"] +) +#%% md +#
+# Inline Exercise: +# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. +# +# Use Shift+Enter to run the cell once you have typed in your code. +#
+#%% +# Todo: Add minimum product flow constraint +#%% +# Todo: Add minimum product flow constraint +m.fs.product_flow = Constraint( + expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] >= 0.15 +) +#%% md +# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. +#%% +m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) +#%% md +# +# We have now defined the optimization problem and we are now ready to solve this problem. +# +# +# +#%% +results = solver.solve(m, tee=True) +#%% +# Check for solver solve status +from pyomo.environ import TerminationCondition + +assert results.solver.termination_condition == TerminationCondition.optimal +#%% md +# ### 8.1 Optimization Results +# +# Display the results and product specifications +#%% +print("operating cost = $", value(m.fs.operating_cost)) + +print() +print("Product flow rate and purity in F102") + +m.fs.F102.report() + +print() +print("benzene purity = ", value(m.fs.purity)) + +print() +print("Overhead loss in F101") +m.fs.F101.report() +#%% +assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3) +assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) +#%% md +# Display optimal values for the decision variables +#%% +print( + f"""Optimal Values: + +H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K + +R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K + +F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K + +F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K +F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa +""" +) +#%% +assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) +assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) +assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3) +assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) \ No newline at end of file From 58eec85faf44628fc6eb15a5634d54adda25b84c Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Wed, 3 Dec 2025 12:11:00 -0700 Subject: [PATCH 35/36] Revised HDA Flowsheet to use the new State Definition FpTPxpc and add the necessary supporting files to make it work. Included a Python file of the flowsheet. --- .../mod/hda/hda_ideal_VLE_modular.py | 236 +- .../mod/hda/hda_reaction_modular.py | 20 +- .../docs/tut/core/hda_flowsheet.ipynb | 2121 ++++- .../notebooks/docs/tut/core/hda_flowsheet.py | 480 +- .../docs/tut/core/hda_flowsheet_doc.ipynb | 7555 +++++++++++------ .../tut/core/hda_flowsheet_exercise.ipynb | 5481 ++++++------ .../tut/core/hda_flowsheet_solution.ipynb | 6108 ++++++------- .../docs/tut/core/hda_flowsheet_test.ipynb | 5831 +++++++------ .../docs/tut/core/hda_flowsheet_usr.ipynb | 6108 ++++++------- .../docs/tut/core/initializing_testing.py | 107 + 10 files changed, 19841 insertions(+), 14206 deletions(-) create mode 100644 idaes_examples/notebooks/docs/tut/core/initializing_testing.py diff --git a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py index 7aaf9f76..13ffff4a 100644 --- a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py +++ b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py @@ -19,26 +19,32 @@ assumptions along with methods drawn from the pre-built IDAES property libraries. """ +import copy + # Import Pyomo units -from pyomo.environ import units as pyunits +from pyomo.environ import units as pyunits, Var, value # Import IDAES cores -from idaes.core import LiquidPhase, VaporPhase, Component +from idaes.core import LiquidPhase, VaporPhase, Component, PhaseType import idaes.logger as idaeslog -from idaes.models.properties.modular_properties.state_definitions import FpcTP +from idaes.core.util.math import smooth_max +from idaes.core.util.constants import Constants + +from idaes.models.properties.modular_properties.state_definitions.FpTPxpc import FpTPxpc from idaes.models.properties.modular_properties.eos.ideal import Ideal from idaes.models.properties.modular_properties.phase_equil import SmoothVLE from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( IdealBubbleDew, ) +from idaes.core.util.misc import set_param_from_config from idaes.models.properties.modular_properties.phase_equil.forms import fugacity from idaes.models.properties.modular_properties.pure import Perrys from idaes.models.properties.modular_properties.pure import RPP5 # Set up logger _log = idaeslog.getLogger(__name__) - +R = value(Constants.gas_constant) # --------------------------------------------------------------------- # Configuration dictionary for an ideal Benzene-Toluene system @@ -48,6 +54,78 @@ # [2] Perry's Chemical Engineers' Handbook 7th Ed. # [3] Engineering Toolbox, https://www.engineeringtoolbox.com # Retrieved 1st December, 2019 +# [4] Properties of Gases and Liquids (2000) 5th edition +# Poling, B. E. and Prausnitz, J. M. and O'Connell, J. P. +# McGraw Hill LLC +# Might be the second printing---copyright was from 2001 + +# Legacy values from [1] +cp_ig_data = { + ("benzene", 0): -3.392e1 / R, + ("benzene", 1): 4.739e-1 / R, + ("benzene", 2): -3.017e-4 / R, + ("benzene", 3): 7.130e-8 / R, + ("benzene", 4): 0, + ("toluene", 0): -2.435e1 / R, + ("toluene", 1): 5.125e-1 / R, + ("toluene", 2): -2.765e-4 / R, + ("toluene", 3): 4.911e-8 / R, + ("toluene", 4): 0, + ("hydrogen", 0): 2.714e1 / R, + ("hydrogen", 1): 9.274e-3 / R, + ("hydrogen", 2): -1.381e-5 / R, + ("hydrogen", 3): 7.645e-9 / R, + ("hydrogen", 4): 0, + ("methane", 0): 1.925e1 / R, + ("methane", 1): 5.213e-2 / R, + ("methane", 2): 1.197e-5 / R, + ("methane", 3): -1.132e-8 / R, + ("methane", 4): 0, +} + + +class PerrysSafe(object): + class dens_mol_liq_comp: + @staticmethod + def build_parameters(cobj): + cobj.dens_mol_liq_comp_coeff_1 = Var( + doc="Parameter 1 for liquid phase molar density", + units=pyunits.kmol * pyunits.m**-3, + ) + set_param_from_config(cobj, param="dens_mol_liq_comp_coeff", index="1") + + cobj.dens_mol_liq_comp_coeff_2 = Var( + doc="Parameter 2 for liquid phase molar density", + units=pyunits.dimensionless, + ) + set_param_from_config(cobj, param="dens_mol_liq_comp_coeff", index="2") + + cobj.dens_mol_liq_comp_coeff_3 = Var( + doc="Parameter 3 for liquid phase molar density", units=pyunits.K + ) + set_param_from_config(cobj, param="dens_mol_liq_comp_coeff", index="3") + + cobj.dens_mol_liq_comp_coeff_4 = Var( + doc="Parameter 4 for liquid phase molar density", + units=pyunits.dimensionless, + ) + set_param_from_config(cobj, param="dens_mol_liq_comp_coeff", index="4") + + @staticmethod + def return_expression(b, cobj, T): + # pg. 2-98 + T = pyunits.convert(T, to_units=pyunits.K) + + rho = cobj.dens_mol_liq_comp_coeff_1 / cobj.dens_mol_liq_comp_coeff_2 ** ( + 1 + + smooth_max(1 - T / cobj.dens_mol_liq_comp_coeff_3, 0) + ** cobj.dens_mol_liq_comp_coeff_4 + ) + + units = b.params.get_metadata().derived_units + + return pyunits.convert(rho, units.DENSITY_MOLE) + thermo_config = { # Specifying components @@ -55,7 +133,7 @@ "benzene": { "type": Component, "elemental_composition": {"C": 6, "H": 6}, - "dens_mol_liq_comp": Perrys, + "dens_mol_liq_comp": PerrysSafe, "enth_mol_liq_comp": Perrys, "enth_mol_ig_comp": RPP5, "pressure_sat_comp": RPP5, @@ -66,38 +144,34 @@ "temperature_crit": (562.2, pyunits.K), # [1] "dens_mol_liq_comp_coeff": { "eqn_type": 1, - "1": (1.0162, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "1": (1.0162, pyunits.kmol * pyunits.m**-3), # [2] pg. 2-98 "2": (0.2655, None), "3": (562.16, pyunits.K), "4": (0.28212, None), }, "cp_mol_ig_comp_coeff": { - "a0": (-3.392e1, None), # [1] - "a1": (4.739e-1, pyunits.K**-1), - "a2": (-3.017e-4, pyunits.K**-2), - "a3": (7.130e-8, pyunits.K**-3), - "a4": (0.0, pyunits.K ** -4), + f"a{k}": (cp_ig_data["benzene", k], pyunits.K**-k) for k in range(5) }, "cp_mol_liq_comp_coeff": { - "1": (1.29e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] - "2": (-1.7e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), - "3": (6.48e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), - "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + "1": (1.29e2 * 1e3, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.7e-1 * 1e3, pyunits.J / pyunits.kmol / pyunits.K**2), + "3": (6.48e-4 * 1e3, pyunits.J / pyunits.kmol / pyunits.K**3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K**4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K**5), }, "enth_mol_form_liq_comp_ref": (49.0e3, pyunits.J / pyunits.mol), # [3] "enth_mol_form_vap_comp_ref": (82.9e3, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (4.202, pyunits.dimensionless), # [1] "B": (1322, pyunits.K), - "C": (-38.56, pyunits.K), + "C": (-38.56 + 273.15, pyunits.K), }, }, }, "toluene": { "type": Component, "elemental_composition": {"C": 7, "H": 8}, - "dens_mol_liq_comp": Perrys, + "dens_mol_liq_comp": PerrysSafe, "enth_mol_liq_comp": Perrys, "enth_mol_ig_comp": RPP5, "pressure_sat_comp": RPP5, @@ -108,119 +182,106 @@ "temperature_crit": (591.8, pyunits.K), # [1] "dens_mol_liq_comp_coeff": { "eqn_type": 1, - "1": (0.8488, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + "1": (0.8488, pyunits.kmol * pyunits.m**-3), # [2] pg. 2-98 "2": (0.26655, None), "3": (591.8, pyunits.K), "4": (0.2878, None), }, "cp_mol_ig_comp_coeff": { - "a0": (-2.435e1, None), # [1] - "a1": (5.125e-1, pyunits.K**-1), - "a2": (-2.765e-4, pyunits.K**-2), - "a3": (4.911e-8, pyunits.K**-3), - "a4": (0.0, pyunits.K ** -4), + f"a{k}": (cp_ig_data["toluene", k], pyunits.K**-k) for k in range(5) }, "cp_mol_liq_comp_coeff": { - "1": (1.40e2, pyunits.J / pyunits.kmol / pyunits.K), # [2] - "2": (-1.52e-1, pyunits.J / pyunits.kmol / pyunits.K ** 2), - "3": (6.95e-4, pyunits.J / pyunits.kmol / pyunits.K ** 3), - "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + "1": (1.40e2 * 1e3, pyunits.J / pyunits.kmol / pyunits.K), # [2] + "2": (-1.52e-1 * 1e3, pyunits.J / pyunits.kmol / pyunits.K**2), + "3": (6.95e-4 * 1e3, pyunits.J / pyunits.kmol / pyunits.K**3), + "4": (0, pyunits.J / pyunits.kmol / pyunits.K**4), + "5": (0, pyunits.J / pyunits.kmol / pyunits.K**5), }, "enth_mol_form_liq_comp_ref": (12.0e3, pyunits.J / pyunits.mol), # [3] "enth_mol_form_vap_comp_ref": (50.1e3, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (4.216, pyunits.dimensionless), # [1] "B": (1435, pyunits.K), - "C": (-43.33, pyunits.K), + "C": (-43.33 + 273.15, pyunits.K), }, }, }, "hydrogen": { "type": Component, + "valid_phase_types": [PhaseType.vaporPhase], "elemental_composition": {"H": 2}, - "dens_mol_liq_comp": Perrys, - "enth_mol_liq_comp": Perrys, "enth_mol_ig_comp": RPP5, "pressure_sat_comp": RPP5, - "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, "parameter_data": { "mw": (2.016e-3, pyunits.kg / pyunits.mol), # [1] "pressure_crit": (12.9e5, pyunits.Pa), # [1] "temperature_crit": (33.0, pyunits.K), # [1] - "dens_mol_liq_comp_coeff": { - "eqn_type": 1, - "1": (5.414, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 - "2": (0.34893, None), - "3": (33.19, pyunits.K), - "4": (0.2706, None), - }, + # "dens_mol_liq_comp_coeff": { + # "eqn_type": 1, + # "1": (5.414, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + # "2": (0.34893, None), + # "3": (33.19, pyunits.K), + # "4": (0.2706, None), + # }, "cp_mol_ig_comp_coeff": { - "a0": (2.714e1, None), # [1] - "a1": (9.274e-3, pyunits.K**-1), - "a2": (-1.381e-5, pyunits.K**-2), - "a3": (7.645e-9, pyunits.K**-3), - "a4": (0.0, pyunits.K ** -4), + f"a{k}": (cp_ig_data["hydrogen", k], pyunits.K**-k) + for k in range(5) }, - "cp_mol_liq_comp_coeff": { - "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] - "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), - "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), - "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), - }, - "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + # "cp_mol_liq_comp_coeff": { + # "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + # "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + # "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + # "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + # "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + # }, + # "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] "enth_mol_form_vap_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (3.543, pyunits.dimensionless), # [1] "B": (99.40, pyunits.K), - "C": (7.726, pyunits.K), + "C": (7.726 + 273.15, pyunits.K), }, }, }, "methane": { "type": Component, + "valid_phase_types": [PhaseType.vaporPhase], "elemental_composition": {"C": 1, "H": 4}, - "dens_mol_liq_comp": Perrys, - "enth_mol_liq_comp": Perrys, "enth_mol_ig_comp": RPP5, "pressure_sat_comp": RPP5, - "phase_equilibrium_form": {("Vap", "Liq"): fugacity}, "parameter_data": { "mw": (16.043e-3, pyunits.kg / pyunits.mol), # [1] "pressure_crit": (4.599e6, pyunits.Pa), # [1] "temperature_crit": (190.564, pyunits.K), # [1] - "dens_mol_liq_comp_coeff": { - "eqn_type": 1, - "1": (2.9214, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 - "2": (0.28976, None), - "3": (190.56, pyunits.K), - "4": (0.28881, None), - }, + # "dens_mol_liq_comp_coeff": { + # "eqn_type": 1, + # "1": (2.9214, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 + # "2": (0.28976, None), + # "3": (190.56, pyunits.K), + # "4": (0.28881, None), + # }, "cp_mol_ig_comp_coeff": { - "a0": (1.925e1, None), # [1] - "a1": (5.213e-2, pyunits.K**-1), - "a2": (1.197e-5, pyunits.K**-2), - "a3": (-1.132e-8, pyunits.K**-3), - "a4": (0.0, pyunits.K**-4), + f"a{k}": (cp_ig_data["methane", k], pyunits.K**-k) for k in range(5) }, - "cp_mol_liq_comp_coeff": { - "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] - "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), - "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), - "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), - }, - "enth_mol_form_liq_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] - "enth_mol_form_vap_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + # "cp_mol_liq_comp_coeff": { + # "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] + # "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), + # "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), + # "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), + # "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), + # }, + # "enth_mol_form_liq_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": ( + -74.52e3, + pyunits.J / pyunits.mol, + ), # [3] "pressure_sat_comp_coeff": { "A": (3.990, pyunits.dimensionless), # [1] "B": (443.0, pyunits.K), - "C": (-0.49, pyunits.K), + "C": (-0.49 + 273.15, pyunits.K), }, }, }, - }, # Specifying phases "phases": { @@ -237,10 +298,10 @@ "temperature": pyunits.K, }, # # Specifying state definition - "state_definition": FpcTP, + "state_definition": FpTPxpc, "state_bounds": { - "flow_mol_phase_comp": (1e-12, .5, 100, pyunits.mol / pyunits.s), - "temperature": (298, 298.15, 1000, pyunits.K), + "flow_mol_phase": (1e-12, 0.5, 100, pyunits.mol / pyunits.s), + "temperature": (273.15, 298.15, 1500, pyunits.K), "pressure": (100000, 101325, 1000000, pyunits.Pa), }, "pressure_ref": (101325, pyunits.Pa), @@ -248,5 +309,12 @@ # Defining phase equilibria "phases_in_equilibrium": [("Vap", "Liq")], "phase_equilibrium_state": {("Vap", "Liq"): SmoothVLE}, - "bubble_dew_method": IdealBubbleDew, + "bubble_dew_method": IdealBubbleDew, # LogBubbleDew, + "include_enthalpy_of_formation": True, } + +thermo_config_vapor = copy.deepcopy(thermo_config) +thermo_config_vapor["phases"].pop("Liq") +thermo_config_vapor.pop("phases_in_equilibrium") +thermo_config_vapor.pop("phase_equilibrium_state") +thermo_config_vapor.pop("bubble_dew_method") diff --git a/idaes_examples/mod/hda/hda_reaction_modular.py b/idaes_examples/mod/hda/hda_reaction_modular.py index 831c8684..a662ad9c 100644 --- a/idaes_examples/mod/hda/hda_reaction_modular.py +++ b/idaes_examples/mod/hda/hda_reaction_modular.py @@ -35,7 +35,9 @@ from idaes.models.properties.modular_properties.phase_equil.forms import fugacity from idaes.models.properties.modular_properties.pure import Perrys from idaes.models.properties.modular_properties.pure import RPP5 -from idaes.models.properties.modular_properties.reactions.rate_forms import power_law_rate +from idaes.models.properties.modular_properties.reactions.rate_forms import ( + power_law_rate, +) from idaes.models.properties.modular_properties.reactions.dh_rxn import constant_dh_rxn from idaes.models.properties.modular_properties.reactions.rate_constant import arrhenius from idaes.models.properties.modular_properties.base.utility import ConcentrationForm @@ -54,8 +56,7 @@ # Retrieved 1st December, 2019 reaction_config = { - - 'rate_reactions': { + "rate_reactions": { "hydrodealkylation": { "stoichiometry": { ("Vap", "benzene"): 1, @@ -69,17 +70,20 @@ "concentration_form": ConcentrationForm.partialPressure, "parameter_data": { "dh_rxn_ref": (-1.08e5, pyunits.J / pyunits.mol), - "arrhenius_const": (6.3e10, pyunits.mol * pyunits.m ** -3 * pyunits.s ** -1 * pyunits.Pa ** -1.5), + "arrhenius_const": ( + 6.3e10, + pyunits.mol * pyunits.m**-3 * pyunits.s**-1 * pyunits.Pa**-1.5, + ), "energy_activation": (217.6e3, pyunits.J / pyunits.mol), "reaction_order": { ("Vap", "benzene"): 0, ("Vap", "toluene"): 1.0, - ("Vap", "hydrogen"): .5, - ("Vap", "methane"): 0, } - } + ("Vap", "hydrogen"): 0.5, + ("Vap", "methane"): 0, + }, + }, } }, - # Set base units of measurement "base_units": { "time": pyunits.s, diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index a9654d09..abfc2b04 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-07-15T22:29:16.862036Z", - "start_time": "2025-07-15T22:29:16.858494Z" + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" } }, "source": [ @@ -38,7 +38,7 @@ "\n", "Author: Jaffer Ghouse
\n", "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", + "Updated: 2025-11-19\n", "\n", "## Learning outcomes\n", "\n", @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:17.440971Z", - "start_time": "2025-07-15T22:29:17.070381Z" + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" } }, "source": [ @@ -132,7 +132,6 @@ " ConcreteModel,\n", " Expression,\n", " Objective,\n", - " SolverFactory,\n", " TransformationFactory,\n", " value,\n", ")\n", @@ -160,8 +159,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:18.862462Z", - "start_time": "2025-07-15T22:29:17.454785Z" + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" } }, "source": [ @@ -174,23 +173,22 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:18.975963Z", - "start_time": "2025-07-15T22:29:18.870712Z" + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" } }, "source": [ "from idaes.models.unit_models import (\n", " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", " Mixer,\n", - " MixerInitializer,\n", " Separator as Splitter,\n", - " SeparatorInitializer,\n", " Heater,\n", " StoichiometricReactor,\n", " Feed,\n", " Product,\n", - ")" + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" ], "outputs": [], "execution_count": 4 @@ -212,8 +210,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-07-15T22:29:18.986206Z", - "start_time": "2025-07-15T22:29:18.983178Z" + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" } }, "source": [ @@ -229,8 +227,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.000804Z", - "start_time": "2025-07-15T22:29:18.997523Z" + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" } }, "source": [ @@ -251,20 +249,16 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.013373Z", - "start_time": "2025-07-15T22:29:19.010633Z" + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" } }, "source": [ "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", "\n", "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" + "from idaes.core.solvers import get_solver" ], "outputs": [], "execution_count": 7 @@ -287,26 +281,11 @@ "
" ] }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.029237Z", - "start_time": "2025-07-15T22:29:19.021824Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.117688Z", - "start_time": "2025-07-15T22:29:19.037801Z" + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" } }, "cell_type": "code", @@ -321,7 +300,7 @@ "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" ], "outputs": [], - "execution_count": 9 + "execution_count": 8 }, { "cell_type": "markdown", @@ -336,8 +315,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:19.131934Z", - "start_time": "2025-07-15T22:29:19.127335Z" + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" } }, "source": [ @@ -345,7 +324,7 @@ "m.fs = FlowsheetBlock(dynamic=False)" ], "outputs": [], - "execution_count": 10 + "execution_count": 9 }, { "cell_type": "markdown", @@ -358,68 +337,18 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T22:29:20.186702Z", - "start_time": "2025-07-15T22:29:19.143102Z" + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" } }, "source": [ - "# m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - "# property_package=m.fs.thermo_params\n", - "# )\n", - "\n", "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", - "# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "2025-07-15 16:29:19 [ERROR] idaes.core.base.process_block: Failure in build: fs.thermo_params\n", - "Traceback (most recent call last):\n", - " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py\", line 41, in _rule_default\n", - " b.build()\n", - " File \"c:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py\", line 470, in build\n", - " for p in self.phase_list:\n", - " ^^^^^^^^^^^^^^^\n", - " File \"C:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py\", line 550, in __getattr__\n", - " raise AttributeError(\n", - "AttributeError: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'\n", - "ERROR: Constructing component 'fs.thermo_params' from data=None failed:\n", - " AttributeError: '_ScalarGenericParameterBlock' object has no attribute\n", - " 'phase_list'\n" - ] - }, - { - "ename": "AttributeError", - "evalue": "'_ScalarGenericParameterBlock' object has no attribute 'phase_list'", - "output_type": "error", - "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[11]\u001B[39m\u001B[32m, line 6\u001B[39m\n\u001B[32m 1\u001B[39m \u001B[38;5;66;03m# m.fs.thermo_params = thermo_props.HDAParameterBlock()\u001B[39;00m\n\u001B[32m 2\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\u001B[39;00m\n\u001B[32m 3\u001B[39m \u001B[38;5;66;03m# property_package=m.fs.thermo_params\u001B[39;00m\n\u001B[32m 4\u001B[39m \u001B[38;5;66;03m# )\u001B[39;00m\n\u001B[32m----> \u001B[39m\u001B[32m6\u001B[39m \u001B[43mm\u001B[49m\u001B[43m.\u001B[49m\u001B[43mfs\u001B[49m\u001B[43m.\u001B[49m\u001B[43mthermo_params\u001B[49m = GenericParameterBlock(**thermo_config)\n\u001B[32m 7\u001B[39m \u001B[38;5;66;03m# m.fs.reaction_params = GenericReactionParameterBlock(property_package=m.fs.thermo_params, **reaction_config)\u001B[39;00m\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:571\u001B[39m, in \u001B[36mBlockData.__setattr__\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 566\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m name \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m.\u001B[34m__dict__\u001B[39m:\n\u001B[32m 567\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(val, Component):\n\u001B[32m 568\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 569\u001B[39m \u001B[38;5;66;03m# Pyomo components are added with the add_component method.\u001B[39;00m\n\u001B[32m 570\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m571\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43madd_component\u001B[49m\u001B[43m(\u001B[49m\u001B[43mname\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mval\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 572\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m 573\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 574\u001B[39m \u001B[38;5;66;03m# Other Python objects are added with the standard __setattr__\u001B[39;00m\n\u001B[32m 575\u001B[39m \u001B[38;5;66;03m# method.\u001B[39;00m\n\u001B[32m 576\u001B[39m \u001B[38;5;66;03m#\u001B[39;00m\n\u001B[32m 577\u001B[39m \u001B[38;5;28msuper\u001B[39m(BlockData, \u001B[38;5;28mself\u001B[39m).\u001B[34m__setattr__\u001B[39m(name, val)\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:1101\u001B[39m, in \u001B[36mBlockData.add_component\u001B[39m\u001B[34m(self, name, val)\u001B[39m\n\u001B[32m 1093\u001B[39m logger.debug(\n\u001B[32m 1094\u001B[39m \u001B[33m\"\u001B[39m\u001B[33mConstructing \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m on \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m from data=\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m\"\u001B[39m,\n\u001B[32m 1095\u001B[39m val.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m,\n\u001B[32m (...)\u001B[39m\u001B[32m 1098\u001B[39m \u001B[38;5;28mstr\u001B[39m(data),\n\u001B[32m 1099\u001B[39m )\n\u001B[32m 1100\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m1101\u001B[39m \u001B[43mval\u001B[49m\u001B[43m.\u001B[49m\u001B[43mconstruct\u001B[49m\u001B[43m(\u001B[49m\u001B[43mdata\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 1102\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m:\n\u001B[32m 1103\u001B[39m err = sys.exc_info()[\u001B[32m1\u001B[39m]\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2233\u001B[39m, in \u001B[36mBlock.construct\u001B[39m\u001B[34m(self, data)\u001B[39m\n\u001B[32m 2231\u001B[39m obj.construct(data.get(name, \u001B[38;5;28;01mNone\u001B[39;00m))\n\u001B[32m 2232\u001B[39m \u001B[38;5;66;03m# Trigger the (normal) initialization of the block\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m2233\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_getitem_when_not_present\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_idx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2234\u001B[39m \u001B[38;5;28;01mfinally\u001B[39;00m:\n\u001B[32m 2235\u001B[39m \u001B[38;5;66;03m# We must allow that id(self) may no longer be in\u001B[39;00m\n\u001B[32m 2236\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data, as _getitem_when_not_present will\u001B[39;00m\n\u001B[32m 2237\u001B[39m \u001B[38;5;66;03m# have already removed the entry for scalar blocks (as the\u001B[39;00m\n\u001B[32m 2238\u001B[39m \u001B[38;5;66;03m# BlockData and the Block component are the same object)\u001B[39;00m\n\u001B[32m 2239\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m data \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:2148\u001B[39m, in \u001B[36mBlock._getitem_when_not_present\u001B[39m\u001B[34m(self, idx)\u001B[39m\n\u001B[32m 2145\u001B[39m data = \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[32m 2147\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m-> \u001B[39m\u001B[32m2148\u001B[39m obj = \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_rule\u001B[49m\u001B[43m(\u001B[49m\u001B[43m_block\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 2149\u001B[39m \u001B[38;5;66;03m# If the user returns a block, transfer over everything\u001B[39;00m\n\u001B[32m 2150\u001B[39m \u001B[38;5;66;03m# they defined into the empty one we created. We do\u001B[39;00m\n\u001B[32m 2151\u001B[39m \u001B[38;5;66;03m# this inside the try block so that any abstract\u001B[39;00m\n\u001B[32m 2152\u001B[39m \u001B[38;5;66;03m# components declared by the rule have the opportunity\u001B[39;00m\n\u001B[32m 2153\u001B[39m \u001B[38;5;66;03m# to be initialized with data from\u001B[39;00m\n\u001B[32m 2154\u001B[39m \u001B[38;5;66;03m# _BlockConstruction.data as they are transferred over.\u001B[39;00m\n\u001B[32m 2155\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m obj \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m _block \u001B[38;5;129;01mand\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(obj, BlockData):\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\initializer.py:351\u001B[39m, in \u001B[36mIndexedCallInitializer.__call__\u001B[39m\u001B[34m(self, parent, idx)\u001B[39m\n\u001B[32m 349\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m._fcn(parent, *idx)\n\u001B[32m 350\u001B[39m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m--> \u001B[39m\u001B[32m351\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43m_fcn\u001B[49m\u001B[43m(\u001B[49m\u001B[43mparent\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43midx\u001B[49m\u001B[43m)\u001B[49m\n", - "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\core\\base\\process_block.py:41\u001B[39m, in \u001B[36m_rule_default\u001B[39m\u001B[34m(b, *args)\u001B[39m\n\u001B[32m 35\u001B[39m \u001B[38;5;250m\u001B[39m\u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 36\u001B[39m \u001B[33;03mDefault rule for ProcessBlock, which calls build(). A different rule can\u001B[39;00m\n\u001B[32m 37\u001B[39m \u001B[33;03mbe specified to add additional build steps, or to not call build at all\u001B[39;00m\n\u001B[32m 38\u001B[39m \u001B[33;03musing the normal rule argument to ProcessBlock init.\u001B[39;00m\n\u001B[32m 39\u001B[39m \u001B[33;03m\"\"\"\u001B[39;00m\n\u001B[32m 40\u001B[39m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[32m---> \u001B[39m\u001B[32m41\u001B[39m \u001B[43mb\u001B[49m\u001B[43m.\u001B[49m\u001B[43mbuild\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[32m 42\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m:\n\u001B[32m 43\u001B[39m logging.getLogger(\u001B[34m__name__\u001B[39m).exception(\u001B[33mf\u001B[39m\u001B[33m\"\u001B[39m\u001B[33mFailure in build: \u001B[39m\u001B[38;5;132;01m{\u001B[39;00mb\u001B[38;5;132;01m}\u001B[39;00m\u001B[33m\"\u001B[39m)\n", - "\u001B[36mFile \u001B[39m\u001B[32mc:\\users\\tanner\\documents\\git\\idaes-pse\\idaes\\models\\properties\\modular_properties\\base\\generic_property.py:470\u001B[39m, in \u001B[36mGenericParameterData.build\u001B[39m\u001B[34m(self)\u001B[39m\n\u001B[32m 468\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28mself\u001B[39m._electrolyte:\n\u001B[32m 469\u001B[39m pc_set = []\n\u001B[32m--> \u001B[39m\u001B[32m470\u001B[39m \u001B[38;5;28;01mfor\u001B[39;00m p \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[43m.\u001B[49m\u001B[43mphase_list\u001B[49m:\n\u001B[32m 471\u001B[39m pobj = \u001B[38;5;28mself\u001B[39m.get_phase(p)\n\u001B[32m 472\u001B[39m pc_list = \u001B[38;5;28mself\u001B[39m.get_phase(p).config.component_list\n", - "\u001B[36mFile \u001B[39m\u001B[32mC:\\ProgramData\\Miniconda3\\envs\\examples\\Lib\\site-packages\\pyomo\\core\\base\\block.py:550\u001B[39m, in \u001B[36mBlockData.__getattr__\u001B[39m\u001B[34m(self, val)\u001B[39m\n\u001B[32m 547\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m _component_decorator(\u001B[38;5;28mself\u001B[39m, ModelComponentFactory.get_class(val))\n\u001B[32m 548\u001B[39m \u001B[38;5;66;03m# Since the base classes don't support getattr, we can just\u001B[39;00m\n\u001B[32m 549\u001B[39m \u001B[38;5;66;03m# throw the \"normal\" AttributeError\u001B[39;00m\n\u001B[32m--> \u001B[39m\u001B[32m550\u001B[39m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mAttributeError\u001B[39;00m(\n\u001B[32m 551\u001B[39m \u001B[33m\"\u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m object has no attribute \u001B[39m\u001B[33m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[33m'\u001B[39m\u001B[33m\"\u001B[39m % (\u001B[38;5;28mself\u001B[39m.\u001B[34m__class__\u001B[39m.\u001B[34m__name__\u001B[39m, val)\n\u001B[32m 552\u001B[39m )\n", - "\u001B[31mAttributeError\u001B[39m: '_ScalarGenericParameterBlock' object has no attribute 'phase_list'" - ] - } + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" ], - "execution_count": 11 + "outputs": [], + "execution_count": 10 }, { "cell_type": "markdown", @@ -432,7 +361,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, "source": [ "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", "\n", @@ -450,7 +384,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 11 }, { "cell_type": "markdown", @@ -478,20 +412,28 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } }, "source": [ "# Todo: Add reactor with the specifications above" ], "outputs": [], - "execution_count": null + "execution_count": 12 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } }, "source": [ "# Todo: Add reactor with the specifications above\n", @@ -504,7 +446,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 13 }, { "cell_type": "markdown", @@ -520,7 +462,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, "source": [ "m.fs.F101 = Flash(\n", " property_package=m.fs.thermo_params,\n", @@ -529,7 +476,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 14 }, { "cell_type": "markdown", @@ -540,7 +487,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, "source": [ "m.fs.S101 = Splitter(\n", " property_package=m.fs.thermo_params,\n", @@ -562,7 +514,7 @@ ")" ], "outputs": [], - "execution_count": null + "execution_count": 15 }, { "cell_type": "markdown", @@ -573,7 +525,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", "\n", @@ -582,7 +539,7 @@ "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], - "execution_count": null + "execution_count": 16 }, { "cell_type": "markdown", @@ -602,14 +559,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, "source": [ "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 17 }, { "cell_type": "markdown", @@ -630,27 +592,35 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet" ], "outputs": [], - "execution_count": null + "execution_count": 18 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } }, "source": [ "# Todo: Connect the H101 outlet to R101 inlet\n", "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 19 }, { "cell_type": "markdown", @@ -661,7 +631,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, "source": [ "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", @@ -670,7 +645,7 @@ "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" ], "outputs": [], - "execution_count": null + "execution_count": 20 }, { "cell_type": "markdown", @@ -681,14 +656,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, "source": [ "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" ], "outputs": [], - "execution_count": null + "execution_count": 21 }, { "cell_type": "markdown", @@ -699,12 +679,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, "source": [ "TransformationFactory(\"network.expand_arcs\").apply_to(m)" ], "outputs": [], - "execution_count": null + "execution_count": 22 }, { "cell_type": "markdown", @@ -726,18 +711,27 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, "source": [ "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", " )\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 23 }, { "cell_type": "markdown", @@ -748,14 +742,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, "source": [ "m.fs.cooling_cost = Expression(\n", " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 24 }, { "cell_type": "markdown", @@ -772,14 +771,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, "source": [ "m.fs.heating_cost = Expression(\n", " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 25 }, { "cell_type": "markdown", @@ -790,39 +794,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, "source": [ "m.fs.operating_cost = Expression(\n", " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", ")" ], "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": {}, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [], - "execution_count": null + "execution_count": 26 }, { "cell_type": "markdown", @@ -836,26 +820,43 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.409008Z", + "start_time": "2025-11-20T21:46:10.382157Z" + } }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 29" ], "outputs": [], - "execution_count": null + "execution_count": 28 }, { "cell_type": "markdown", @@ -866,21 +867,32 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", "m.fs.I101.temperature.fix(303.2)\n", "m.fs.I101.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 29 }, { "cell_type": "markdown", @@ -900,21 +912,36 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", "m.fs.I102.temperature.fix(303.2)\n", "m.fs.I102.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 30 }, { "cell_type": "markdown", @@ -927,12 +954,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.fix(600)" ], "outputs": [], - "execution_count": null + "execution_count": 31 }, { "cell_type": "markdown", @@ -943,15 +975,23 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, "source": [ "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", "\n", "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", " )\n", ")\n", "\n", @@ -959,7 +999,7 @@ "m.fs.R101.heat_duty.fix(0)" ], "outputs": [], - "execution_count": null + "execution_count": 32 }, { "cell_type": "markdown", @@ -970,13 +1010,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", "m.fs.F101.deltaP.fix(0)" ], "outputs": [], - "execution_count": null + "execution_count": 33 }, { "cell_type": "markdown", @@ -1003,27 +1048,35 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } }, "source": [ "# Todo: Set conditions for Flash F102" ], "outputs": [], - "execution_count": null + "execution_count": 34 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } }, "source": [ "m.fs.F102.vap_outlet.temperature.fix(375)\n", "m.fs.F102.deltaP.fix(-200000)" ], "outputs": [], - "execution_count": null + "execution_count": 35 }, { "cell_type": "markdown", @@ -1034,13 +1087,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, "source": [ "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", "m.fs.C101.outlet.pressure.fix(350000)" ], "outputs": [], - "execution_count": null + "execution_count": 36 }, { "cell_type": "markdown", @@ -1063,51 +1121,60 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } }, "source": [ "# Todo: print the degrees of freedom" ], "outputs": [], - "execution_count": null + "execution_count": 37 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } }, "source": [ "print(degrees_of_freedom(m))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.568992Z", + "start_time": "2025-11-20T21:46:10.542995Z" + } }, "source": [ "# Check the degrees of freedom\n", "assert degrees_of_freedom(m) == 0" ], "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ] - }, - "source": [], - "outputs": [], - "execution_count": null + "execution_count": 39 }, { "cell_type": "markdown", @@ -1140,7 +1207,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, "source": [ "seq = SequentialDecomposition()\n", "seq.options.select_tear_method = \"heuristic\"\n", @@ -1153,7 +1225,7 @@ "order = seq.calculation_order(G)" ], "outputs": [], - "execution_count": null + "execution_count": 40 }, { "cell_type": "markdown", @@ -1164,13 +1236,26 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, "source": [ "for o in heuristic_tear_set:\n", " print(o.name)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 }, { "cell_type": "markdown", @@ -1182,14 +1267,31 @@ { "cell_type": "code", "metadata": { - "scrolled": true + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } }, "source": [ "for o in order:\n", " print(o[0].name)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 }, { "cell_type": "markdown", @@ -1205,18 +1307,25 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, "source": [ "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", " },\n", " \"temperature\": {0: 303},\n", " \"pressure\": {0: 350000},\n", @@ -1226,7 +1335,7 @@ "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" ], "outputs": [], - "execution_count": null + "execution_count": 43 }, { "cell_type": "markdown", @@ -1237,7 +1346,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, "source": [ "def function(unit):\n", " try:\n", @@ -1248,7 +1362,7 @@ " solver.solve(unit)" ], "outputs": [], - "execution_count": null + "execution_count": 44 }, { "cell_type": "markdown", @@ -1259,12 +1373,567 @@ }, { "cell_type": "code", - "metadata": {}, - "source": [ - "# seq.run(m, function)" + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } ], - "outputs": [], - "execution_count": null + "execution_count": 45 }, { "cell_type": "markdown", @@ -1278,12 +1947,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, "source": [ "from idaes.core.util.initialization import propagate_state" ], "outputs": [], - "execution_count": null + "execution_count": 46 }, { "cell_type": "markdown", @@ -1296,12 +1970,15 @@ }, { "cell_type": "code", - "metadata": {}, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", "outputs": [], - "execution_count": null + "execution_count": 47 }, { "cell_type": "markdown", @@ -1312,14 +1989,19 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" ], "outputs": [], - "execution_count": null + "execution_count": 48 }, { "cell_type": "markdown", @@ -1330,32 +2012,40 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" ], "outputs": [], - "execution_count": null + "execution_count": 49 }, { "cell_type": "markdown", @@ -1366,38 +2056,45 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [], - "execution_count": null + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 }, { "cell_type": "markdown", @@ -1408,7 +2105,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1416,11 +2118,92 @@ " \"max_iter\": 300,\n", " \"tol\": 1e-8,\n", "}\n", - "solver = get_solver(options=optarg)\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 }, { "cell_type": "markdown", @@ -1431,7 +2214,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, "source": [ "for k, v in tear_guesses.items():\n", " for k1, v1 in v.items():\n", @@ -1442,8 +2230,16 @@ " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", ")" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 }, { "cell_type": "markdown", @@ -1463,7 +2259,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, "source": [ "optarg = {\n", " \"nlp_scaling_method\": \"user-scaling\",\n", @@ -1473,7 +2274,7 @@ "}" ], "outputs": [], - "execution_count": null + "execution_count": 53 }, { "cell_type": "markdown", @@ -1499,7 +2300,11 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } }, "source": [ "# Create the solver object\n", @@ -1507,31 +2312,118 @@ "# Solve the model" ], "outputs": [], - "execution_count": null + "execution_count": 54 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } }, "source": [ "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", "\n", "# Solve the model\n", "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.393870Z", + "start_time": "2025-11-20T21:46:17.390132Z" + } }, "source": [ "# Check solver solve status\n", @@ -1540,7 +2432,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": null + "execution_count": 56 }, { "cell_type": "markdown", @@ -1563,13 +2455,17 @@ "metadata": { "tags": [ "noauto" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } }, "source": [ "# m.fs.visualize(\"HDA-Flowsheet\")" ], "outputs": [], - "execution_count": null + "execution_count": 57 }, { "cell_type": "markdown", @@ -1580,12 +2476,38 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, "source": [ "m.fs.report()" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 }, { "cell_type": "markdown", @@ -1596,27 +2518,44 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.571498Z", + "start_time": "2025-11-20T21:46:17.493194Z" + } }, "source": [ "import pytest\n", "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" + "assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 60 }, { "cell_type": "markdown", @@ -1627,30 +2566,81 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, "source": [ "m.fs.F102.report()\n", "\n", "print()\n", "print(\"benzene purity = \", value(m.fs.purity))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.619054Z", + "start_time": "2025-11-20T21:46:17.613393Z" + } }, "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 62 }, { "cell_type": "markdown", @@ -1661,7 +2651,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, "source": [ "from idaes.core.util.tables import (\n", " create_stream_table_dataframe,\n", @@ -1671,8 +2666,23 @@ "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", "print(stream_table_dataframe_to_string(st))" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 }, { "cell_type": "markdown", @@ -1705,12 +2715,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" ], "outputs": [], - "execution_count": null + "execution_count": 64 }, { "cell_type": "markdown", @@ -1721,7 +2736,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, "source": [ "m.fs.H101.outlet.temperature.unfix()\n", "m.fs.R101.heat_duty.unfix()\n", @@ -1729,7 +2749,7 @@ "m.fs.F102.vap_outlet.temperature.unfix()" ], "outputs": [], - "execution_count": null + "execution_count": 65 }, { "cell_type": "markdown", @@ -1753,40 +2773,52 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } }, "source": [ "# Todo: Unfix deltaP for F102" ], "outputs": [], - "execution_count": null + "execution_count": 66 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } }, "source": [ "# Todo: Unfix deltaP for F102\n", "m.fs.F102.deltaP.unfix()" ], "outputs": [], - "execution_count": null + "execution_count": 67 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.759351Z", + "start_time": "2025-11-20T21:46:17.728327Z" + } }, "source": [ "assert degrees_of_freedom(m) == 5" ], "outputs": [], - "execution_count": null + "execution_count": 68 }, { "cell_type": "markdown", @@ -1805,13 +2837,18 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, "source": [ "m.fs.H101.outlet.temperature[0].setlb(500)\n", "m.fs.H101.outlet.temperature[0].setub(600)" ], "outputs": [], - "execution_count": null + "execution_count": 69 }, { "cell_type": "markdown", @@ -1834,20 +2871,28 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } }, "source": [ "# Todo: Set the bounds for reactor outlet temperature" ], "outputs": [], - "execution_count": null + "execution_count": 70 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } }, "source": [ "# Todo: Set the bounds for reactor outlet temperature\n", @@ -1855,7 +2900,7 @@ "m.fs.R101.outlet.temperature[0].setub(800)" ], "outputs": [], - "execution_count": null + "execution_count": 71 }, { "cell_type": "markdown", @@ -1866,7 +2911,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, "source": [ "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", @@ -1876,7 +2926,7 @@ "m.fs.F102.vap_outlet.pressure[0].setub(110000)" ], "outputs": [], - "execution_count": null + "execution_count": 72 }, { "cell_type": "markdown", @@ -1887,15 +2937,23 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, "source": [ "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 73 }, { "cell_type": "markdown", @@ -1918,29 +2976,40 @@ "metadata": { "tags": [ "exercise" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } }, "source": [ "# Todo: Add minimum product flow constraint" ], "outputs": [], - "execution_count": null + "execution_count": 74 }, { "cell_type": "code", "metadata": { "tags": [ "solution" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } }, "source": [ "# Todo: Add minimum product flow constraint\n", "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", ")" ], "outputs": [], - "execution_count": null + "execution_count": 75 }, { "cell_type": "markdown", @@ -1951,12 +3020,17 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" ], "outputs": [], - "execution_count": null + "execution_count": 76 }, { "cell_type": "markdown", @@ -1970,19 +3044,134 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, "source": [ "results = solver.solve(m, tee=True)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.045752Z", + "start_time": "2025-11-20T21:46:18.041549Z" + } }, "source": [ "# Check for solver solve status\n", @@ -1991,7 +3180,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": null + "execution_count": 78 }, { "cell_type": "markdown", @@ -2004,7 +3193,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, "source": [ "print(\"operating cost = $\", value(m.fs.operating_cost))\n", "\n", @@ -2020,22 +3214,106 @@ "print(\"Overhead loss in F101\")\n", "m.fs.F101.report()" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.093619Z", + "start_time": "2025-11-20T21:46:18.090039Z" + } }, "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", + "assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" ], "outputs": [], - "execution_count": null + "execution_count": 80 }, { "cell_type": "markdown", @@ -2046,7 +3324,12 @@ }, { "cell_type": "code", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, "source": [ "print(\n", " f\"\"\"Optimal Values:\n", @@ -2062,25 +3345,67 @@ "\"\"\"\n", ")" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 }, { "cell_type": "code", "metadata": { "tags": [ "testing" - ] + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:19.262061Z", + "start_time": "2025-11-20T21:46:18.121920Z" + } }, "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", + "print(value(m.fs.R101.outlet.temperature[0]))\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "763.5072359720118\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAssertionError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[82]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.H101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m500\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m763.484\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F101.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m301.881\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 5\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F102.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m362.935\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n", + "\u001b[31mAssertionError\u001b[39m: " + ] + } + ], + "execution_count": 82 } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py index 39b56e2f..57eac3e4 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py @@ -1,11 +1,9 @@ - from pyomo.environ import ( Constraint, Var, ConcreteModel, Expression, Objective, - SolverFactory, TransformationFactory, value, ) @@ -15,35 +13,26 @@ from idaes.models.unit_models import ( PressureChanger, - IsentropicPressureChangerInitializer, Mixer, - MixerInitializer, Separator as Splitter, - SeparatorInitializer, Heater, StoichiometricReactor, Feed, Product, ) +from idaes.core.util.exceptions import InitializationError +import idaes.logger as idaeslog + # Todo: import flash model from idaes.models.unit_models # Todo: import flash model from idaes.models.unit_models from idaes.models.unit_models import Flash - from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption from idaes.core.util.model_statistics import degrees_of_freedom -from idaes.core.scaling.util import set_scaling_factor -from idaes.core.scaling.autoscaling import AutoScaler - -import idaes.logger as idaeslog from idaes.core.solvers import get_solver -from idaes.core.util.exceptions import InitializationError - -from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props -from idaes_examples.mod.hda import hda_reaction as reaction_props from idaes.models.properties.modular_properties.base.generic_property import ( GenericParameterBlock, @@ -54,22 +43,15 @@ from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config from idaes_examples.mod.hda.hda_reaction_modular import reaction_config - m = ConcreteModel() m.fs = FlowsheetBlock(dynamic=False) -thermo_params_og = thermo_props.HDAParameterBlock() -reaction_params_og = reaction_props.HDAReactionParameterBlock(property_package=thermo_params_og) -thermo_params_new = GenericParameterBlock(**thermo_config) -reaction_params_new = GenericReactionParameterBlock(property_package=thermo_params_new, **reaction_config) - -# m.fs.thermo_params = thermo_params_og -# m.fs.reaction_params = reaction_params_og -m.fs.thermo_params = thermo_params_new -m.fs.reaction_params = reaction_params_new +m.fs.thermo_params = GenericParameterBlock(**thermo_config) +m.fs.reaction_params = GenericReactionParameterBlock( + property_package=m.fs.thermo_params, **reaction_config +) m.fs.I101 = Feed(property_package=m.fs.thermo_params) - m.fs.I102 = Feed(property_package=m.fs.thermo_params) m.fs.M101 = Mixer( @@ -103,7 +85,6 @@ outlet_list=["purge", "recycle"], ) - m.fs.C101 = PressureChanger( property_package=m.fs.thermo_params, compressor=True, @@ -136,10 +117,14 @@ TransformationFactory("network.expand_arcs").apply_to(m) m.fs.purity = Expression( - expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] / ( - m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] - + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "toluene"] + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] + + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "toluene" + ] ) ) @@ -155,32 +140,43 @@ expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) ) -# autoscaler = AutoScaler() -# autoscaler.scale_model(m) +assert degrees_of_freedom(m) == 29 -print(degrees_of_freedom(m)) +F_liq_toluene = 0.30 +F_liq_non_zero = 1e-5 -assert degrees_of_freedom(m) == 29 +F_vap_I101 = F_liq_non_zero * 4 +F_liq_I101 = F_liq_toluene + F_liq_non_zero -m.fs.I101.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Vap", "methane"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "toluene"].fix(0.30) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) -m.fs.I101.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +m.fs.I101.flow_mol_phase[0, "Vap"].fix(F_vap_I101) +m.fs.I101.flow_mol_phase[0, "Liq"].fix(F_liq_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_liq_non_zero / F_vap_I101) +m.fs.I101.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I101) +m.fs.I101.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_toluene / F_liq_I101) m.fs.I101.temperature.fix(303.2) m.fs.I101.pressure.fix(350000) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "benzene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "toluene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "hydrogen"].fix(0.30) -m.fs.I102.flow_mol_phase_comp[0, "Vap", "methane"].fix(0.02) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "benzene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "toluene"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "hydrogen"].fix(1e-5) -m.fs.I102.flow_mol_phase_comp[0, "Liq", "methane"].fix(1e-5) +F_vap_hydrogen = 0.30 +F_vap_methane = 0.020 + +F_vap_non_zero = 1e-5 +F_liq_non_zero = F_vap_non_zero + +F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero +F_liq_I102 = 2 * F_vap_non_zero + +m.fs.I102.flow_mol_phase[0, "Vap"].fix(F_vap_I102) +m.fs.I102.flow_mol_phase[0, "Liq"].fix(F_liq_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_vap_non_zero / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_vap_non_zero / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_vap_hydrogen / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_vap_methane / F_vap_I102) +m.fs.I102.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I102) +m.fs.I102.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_non_zero / F_liq_I102) + m.fs.I102.temperature.fix(303.2) m.fs.I102.pressure.fix(350000) @@ -189,8 +185,15 @@ m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) m.fs.R101.conv_constraint = Constraint( - expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - == (m.fs.R101.inlet.flow_mol_phase_comp[0, "Vap", "toluene"] - m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "toluene"])) + expr=m.fs.R101.conversion + * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"]) + == ( + m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"] + - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "toluene" + ] + ) +) m.fs.R101.conversion.fix(0.75) m.fs.R101.heat_duty.fix(0) @@ -204,93 +207,107 @@ m.fs.S101.split_fraction[0, "purge"].fix(0.2) m.fs.C101.outlet.pressure.fix(350000) -from idaes.core.util.initialization import propagate_state +seq = SequentialDecomposition() +seq.options.select_tear_method = "heuristic" +seq.options.tear_method = "Wegstein" +seq.options.iterLim = 3 + +# Using the SD tool +G = seq.create_graph(m) +heuristic_tear_set = seq.tear_set_arcs(G, method="heuristic") +order = seq.calculation_order(G) + +for o in heuristic_tear_set: + print(o.name) + +for o in order: + print(o[0].name) -print(f"The DOF is {degrees_of_freedom(m)} initially") -m.fs.s03_expanded.deactivate() -print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") tear_guesses = { - "flow_mol_phase_comp": { - (0, "Liq", "benzene"): 1e-5, - (0, "Liq", "toluene"): 0.30, - (0, "Liq", "methane"): 1e-5, - (0, "Liq", "hydrogen"): 1e-5, - (0, "Vap", "benzene"): 1e-5, - (0, "Vap", "toluene"): 1e-5, - (0, "Vap", "methane"): 0.5, - (0, "Vap", "hydrogen"): 0.5, + "flow_mol_phase": { + (0, "Liq"): F_liq_I101, + (0, "Vap"): F_vap_I102, + }, + "mole_frac_phase_comp": { + (0, "Liq", "benzene"): 1e-5 / F_liq_I101, + (0, "Liq", "toluene"): 0.30 / F_liq_I101, + (0, "Vap", "benzene"): 1e-5 / F_vap_I102, + (0, "Vap", "toluene"): 1e-5 / F_vap_I102, + (0, "Vap", "methane"): 0.02 / F_vap_I102, + (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, }, "temperature": {0: 303}, "pressure": {0: 350000}, } -for k, v in tear_guesses.items(): - for k1, v1 in v.items(): - getattr(m.fs.s03.destination, k)[k1].fix(v1) - -DOF_initial = degrees_of_freedom(m) -# x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) -# x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) -# x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) -# x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) - -# p_sat_dewT_0 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['benzene']) -# p_sat_dewT_1 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['toluene']) -# p_sat_dewT_2 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['hydrogen']) -# p_sat_dewT_3 = value(m.fs.H101.control_volume.properties_out[0.0]._p_sat_dewT['methane']) -# -# print(p_sat_dewT_0) -# print(p_sat_dewT_1) -# print(p_sat_dewT_2) -# print(p_sat_dewT_3) +# Pass the tear_guess to the SD tool +seq.set_guesses_for(m.fs.H101.inlet, tear_guesses) + + +def function(unit): + try: + initializer = unit.default_initializer() + initializer.initialize(unit, output_level=idaeslog.INFO) + except InitializationError: + solver = get_solver() + solver.solve(unit) +seq.run(m, function) + +# from idaes.core.util.initialization import propagate_state # -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['benzene'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['toluene'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['hydrogen'])) -# print(value(m.fs.H101.control_volume.properties_out[0.0].pressure_sat_comp['methane'])) +# print(f"The DOF is {degrees_of_freedom(m)} initially") +# m.fs.s03_expanded.deactivate() +# print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") # -# print(value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew['Vap', 'Liq'])) - -# P = value(m.fs.H101.control_volume.properties_out[0.0].pressure) +# tear_guesses = { +# "flow_mol_phase": { +# (0, "Liq"): F_liq_I101, +# (0, "Vap"): F_vap_I102, # -# print(P*(x_0/p_sat_dewT_0 + x_1/p_sat_dewT_1) - 1) - - -m.fs.H101.default_initializer().initialize(m.fs.H101, output_level=idaeslog.INFO_HIGH) # Initialize Heater -x_0 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['benzene']) -x_1 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['toluene']) -x_2 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['hydrogen']) -x_3 = value(m.fs.H101.control_volume.properties_out[0.0].mole_frac_comp['methane']) - -T_dew = value(m.fs.H101.control_volume.properties_out[0.0].temperature_dew) -T_bub = value(m.fs.H101.control_volume.properties_out[0.0].temperature_bubble) -P_dew = value(m.fs.H101.control_volume.properties_out[0.0].pressure_dew) -P_bub = value(m.fs.H101.control_volume.properties_out[0.0].pressure_bubble) - -m.fs.H101.default_initializer().initialize(m.fs.H101) -propagate_state(m.fs.s04) # Establish connection between Heater and Reactor -m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor -propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit -m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit -propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter -propagate_state(m.fs.s07) -m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter -propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor -m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor -propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer -m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet -propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer -m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet -propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer -m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer -propagate_state(m.fs.s03) # Establish connection between Mixer and Heater -m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit -propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product -propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product -propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product - +# }, +# "mole_frac_phase_comp": { +# (0, "Liq", "benzene"): 1e-5 / F_liq_I101, +# (0, "Liq", "toluene"): 0.30 / F_liq_I101, +# (0, "Vap", "benzene"): 1e-5 / F_vap_I102, +# (0, "Vap", "toluene"): 1e-5 / F_vap_I102, +# (0, "Vap", "methane"): 0.02 / F_vap_I102, +# (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, +# }, +# "temperature": {0: 303}, +# "pressure": {0: 350000}, +# } +# +# for k, v in tear_guesses.items(): +# for k1, v1 in v.items(): +# getattr(m.fs.s03.destination, k)[k1].fix(v1) +# +# DOF_initial = degrees_of_freedom(m) +# +# print(f"The DOF is {degrees_of_freedom(m)} after setting the tear stream") +# +# m.fs.H101.default_initializer().initialize(m.fs.H101) +# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor +# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor +# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit +# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit +# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter +# propagate_state(m.fs.s07) +# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter +# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor +# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor +# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer +# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet +# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer +# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet +# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer +# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer +# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater +# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit +# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product +# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product +# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product optarg = { "nlp_scaling_method": "user-scaling", @@ -298,10 +315,9 @@ "max_iter": 300, "tol": 1e-8, } -solver = get_solver(options=optarg) +solver = get_solver("ipopt_v2", options=optarg) results = solver.solve(m, tee=True) - for k, v in tear_guesses.items(): for k1, v1 in v.items(): getattr(m.fs.H101.inlet, k)[k1].unfix() @@ -310,79 +326,81 @@ print( f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" ) -#%% md +# %% md # ## 6 Solving the Model -#%% md +# %% md # We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html -#%% +# %% optarg = { "nlp_scaling_method": "user-scaling", "OF_ma57_automatic_scaling": "yes", "max_iter": 1000, "tol": 1e-8, } -#%% md +# %% md #
# Inline Exercise: # Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following: -# +# # solver = get_solver(solver_options=optarg)
# results = solver.solve(m, tee=True) -# +# # Use Shift+Enter to run the cell once you have typed in your code. #
-# -#%% +# +# %% # Create the solver object # Solve the model -#%% +# %% # Create the solver object -solver = get_solver(solver_options=optarg) +solver = get_solver("ipopt_v2", options=optarg) # Solve the model -results = solver.solve(m, tee=True) -#%% +results = solver.solve(m, tee=False) + +print(f"Solver result: {results}") +# %% # Check solver solve status from pyomo.environ import TerminationCondition assert results.solver.termination_condition == TerminationCondition.optimal -#%% md +# %% md # ## 7 Analyze the results -# -# -# -#%% md +# +# +# +# %% md # If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window. -# -#%% +# +# %% # m.fs.visualize("HDA-Flowsheet") -#%% md +# %% md # Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display. -#%% +# %% m.fs.report() -#%% md +# %% md # What is the total operating cost? -#%% +# %% print("operating cost = $", value(m.fs.operating_cost)) -#%% +# %% import pytest -assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3) -#%% md +# assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3) +# %% md # For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method. -#%% +# %% m.fs.F102.report() print() print("benzene purity = ", value(m.fs.purity)) -#%% +# %% assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) -assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3) +assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3) assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) -#%% md +# %% md # Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101. -#%% +# %% from idaes.core.util.tables import ( create_stream_table_dataframe, stream_table_dataframe_to_string, @@ -390,129 +408,135 @@ st = create_stream_table_dataframe({"Reactor": m.fs.s05, "Light Gases": m.fs.s06}) print(stream_table_dataframe_to_string(st)) -#%% md +# %% md # ## 8 Optimization -# -# -# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. -# +# +# +# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. +# # Let us try to minimize this cost such that: # - we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream # - purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80% # - restricting the benzene loss in F101 vapor outlet to less than 20% -# +# # For this problem, our decision variables are as follows: # - H101 outlet temperature # - R101 cooling duty provided # - F101 outlet temperature # - F102 outlet temperature # - F102 deltaP in the flash tank -# -#%% md -# Let us declare our objective function for this problem. -#%% +# +# %% md +# Let us declare our objective function for this problem. +# %% m.fs.objective = Objective(expr=m.fs.operating_cost) -#%% md -# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. -#%% +# %% md +# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. +# %% m.fs.H101.outlet.temperature.unfix() m.fs.R101.heat_duty.unfix() m.fs.F101.vap_outlet.temperature.unfix() m.fs.F102.vap_outlet.temperature.unfix() -#%% md +# %% md #
# Inline Exercise: -# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) -# -# Use Shift+Enter to run the cell once you have typed in your code. +# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-# -# -#%% +# +# +# %% # Todo: Unfix deltaP for F102 -#%% +# %% # Todo: Unfix deltaP for F102 m.fs.F102.deltaP.unfix() -#%% +# %% assert degrees_of_freedom(m) == 5 -#%% md +# %% md # Next, we need to set bounds on these decision variables to values shown below: -# +# # - H101 outlet temperature [500, 600] K # - R101 outlet temperature [600, 800] K # - F101 outlet temperature [298, 450] K # - F102 outlet temperature [298, 450] K # - F102 outlet pressure [105000, 110000] Pa -# +# # Let us first set the variable bound for the H101 outlet temperature as shown below: -#%% +# %% m.fs.H101.outlet.temperature[0].setlb(500) m.fs.H101.outlet.temperature[0].setub(600) -#%% md +# %% md #
# Inline Exercise: # Now, set the variable bound for the R101 outlet temperature. -# -# Use Shift+Enter to run the cell once you have typed in your code. +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-#%% +# %% # Todo: Set the bounds for reactor outlet temperature -#%% +# %% # Todo: Set the bounds for reactor outlet temperature m.fs.R101.outlet.temperature[0].setlb(600) m.fs.R101.outlet.temperature[0].setub(800) -#%% md -# Let us fix the bounds for the rest of the decision variables. -#%% +# %% md +# Let us fix the bounds for the rest of the decision variables. +# %% m.fs.F101.vap_outlet.temperature[0].setlb(298.0) m.fs.F101.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.temperature[0].setlb(298.0) m.fs.F102.vap_outlet.temperature[0].setub(450.0) m.fs.F102.vap_outlet.pressure[0].setlb(105000) m.fs.F102.vap_outlet.pressure[0].setub(110000) -#%% md -# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. -#%% +# %% md +# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. +# %% m.fs.overhead_loss = Constraint( - expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] - <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, "Vap", "benzene"] + expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + <= 0.20 + * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] ) -#%% md +# %% md #
# Inline Exercise: -# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. -# -# Use Shift+Enter to run the cell once you have typed in your code. +# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. +# +# Use Shift+Enter to run the cell once you have typed in your code. #
-#%% +# %% # Todo: Add minimum product flow constraint -#%% +# %% # Todo: Add minimum product flow constraint m.fs.product_flow = Constraint( - expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, "Vap", "benzene"] >= 0.15 + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + >= 0.15 ) -#%% md -# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. -#%% +# %% md +# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. +# %% m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) -#%% md -# -# We have now defined the optimization problem and we are now ready to solve this problem. -# -# -# -#%% +# %% md +# +# We have now defined the optimization problem and we are now ready to solve this problem. +# +# +# +# %% results = solver.solve(m, tee=True) -#%% +# %% # Check for solver solve status from pyomo.environ import TerminationCondition assert results.solver.termination_condition == TerminationCondition.optimal -#%% md +# %% md # ### 8.1 Optimization Results -# +# # Display the results and product specifications -#%% +# %% print("operating cost = $", value(m.fs.operating_cost)) print() @@ -526,12 +550,13 @@ print() print("Overhead loss in F101") m.fs.F101.report() -#%% -assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3) +# %% + +assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3) assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) -#%% md +# %% md # Display optimal values for the decision variables -#%% +# %% print( f"""Optimal Values: @@ -545,9 +570,10 @@ F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa """ ) -#%% +# %% assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) -assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) -assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3) +# assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) +assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3) +assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3) assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) -assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) \ No newline at end of file +assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb index 219269e0..22c9fbaa 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_doc.ipynb @@ -1,2543 +1,5016 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + }, + "tags": [ + "header", + "hide-cell" + ] + }, + "outputs": [], + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "outputs": [], + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "outputs": [], + "source": [ + "from idaes.core import FlowsheetBlock" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "outputs": [], + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "outputs": [], + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "outputs": [], + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "outputs": [], + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "outputs": [], + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "outputs": [], + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "outputs": [], + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "outputs": [], + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "outputs": [], + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "outputs": [], + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "outputs": [], + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "outputs": [], + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "source": [ + "print(degrees_of_freedom(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "outputs": [], + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "outputs": [], + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "outputs": [], + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "outputs": [], + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "source": [ + "print(degrees_of_freedom(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "outputs": [], + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "source": [ + "for o in order:\n", + " print(o[0].name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "outputs": [], + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "outputs": [], + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"fs.R101\";\n", + " - termination condition: infeasible\n", + " - message from solver: Ipopt 3.13.2\\x3a Converged to a locally infeasible\n", + " point. Problem may be infeasible.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:40 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:41 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: Loading a SolverResults object with a warning status into\n", + "model.name=\"fs.R101\";\n", + " - termination condition: infeasible\n", + " - message from solver: Ipopt 3.13.2\\x3a Converged to a locally infeasible\n", + " point. Problem may be infeasible.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:42 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-25 12:36:43 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "source": [ + "seq.run(m, function)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "outputs": [], + "source": [ + "from idaes.core.util.initialization import propagate_state" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "outputs": [], + "source": [ + "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "outputs": [], + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "outputs": [], + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "outputs": [], + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpoctkmbii\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpoctkmbii\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 155\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.74e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reallocating memory for MA57: lfact (10193)\n", + " 1r 0.0000000e+00 3.74e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 3.17e-07R 3\n", + " 2r 0.0000000e+00 6.21e+04 1.21e+03 3.6 3.74e+06 - 3.68e-03 3.56e-04f 1\n", + " 3r 0.0000000e+00 5.77e+04 1.09e+05 3.6 5.16e+05 - 9.43e-02 4.63e-03f 1\n", + " 4r 0.0000000e+00 5.24e+04 6.21e+04 3.6 3.34e+03 - 2.55e-01 9.98e-02f 1\n", + " 5r 0.0000000e+00 6.56e+04 1.25e+05 3.6 1.51e+02 - 6.91e-01 4.02e-01f 1\n", + " 6r 0.0000000e+00 4.50e+04 2.67e+04 3.6 3.07e+01 - 1.00e+00 7.13e-01f 1\n", + " 7r 0.0000000e+00 1.83e+04 7.35e+03 3.6 3.08e+01 - 1.00e+00 1.00e+00f 1\n", + " 8r 0.0000000e+00 3.31e+04 4.68e+03 2.9 3.73e+01 - 7.83e-01 8.25e-01f 1\n", + " 9r 0.0000000e+00 1.06e+04 6.58e+02 2.9 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 6.29e+03 4.93e+02 2.9 2.70e+01 - 1.00e+00 1.00e+00h 1\n", + " 11r 0.0000000e+00 5.23e+04 5.25e+02 2.2 2.33e+01 - 9.63e-01 9.78e-01f 1\n", + " 12r 0.0000000e+00 7.01e+03 1.04e+02 2.2 2.10e+01 - 1.00e+00 1.00e+00f 1\n", + " 13r 0.0000000e+00 8.17e+02 1.95e+01 2.2 5.26e+00 - 1.00e+00 1.00e+00f 1\n", + " 14r 0.0000000e+00 5.65e+03 7.52e+02 1.5 1.79e+01 - 8.36e-01 9.57e-01f 1\n", + " 15r 0.0000000e+00 1.39e+04 5.80e+02 1.5 7.56e+01 - 7.87e-01 5.50e-01f 1\n", + " 16r 0.0000000e+00 1.86e+04 4.51e+02 1.5 1.21e+01 - 6.10e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.25e+04 2.51e+02 1.5 1.27e+01 - 7.28e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 8.69e+02 4.46e+01 1.5 9.42e+00 - 1.00e+00 1.00e+00h 1\n", + " 19r 0.0000000e+00 2.75e+02 1.30e+00 1.5 2.78e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 3.71e+03 2.13e+02 0.8 1.88e+01 - 9.33e-01 9.68e-01f 1\n", + " 21r 0.0000000e+00 9.91e+01 1.22e+02 0.8 1.24e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 2.87e+01 1.01e+03 0.8 4.55e-01 1.5 3.90e-01 9.98e-01H 1\n", + " 23r 0.0000000e+00 4.95e+02 1.46e+02 0.8 4.53e-01 1.0 1.00e+00 9.27e-01f 1\n", + " 24r 0.0000000e+00 4.75e+02 3.38e+02 0.8 4.95e-01 1.5 6.73e-01 8.53e-01f 1\n", + " 25r 0.0000000e+00 2.04e+02 7.82e+01 0.8 7.99e-02 2.8 1.00e+00 1.00e+00f 1\n", + " 26r 0.0000000e+00 2.86e+02 1.37e+02 0.8 9.62e-01 2.3 2.38e-01 2.31e-01f 1\n", + " 27r 0.0000000e+00 2.57e+02 7.76e+02 0.8 7.36e-01 1.8 4.15e-01 7.40e-02f 1\n", + " 28r 0.0000000e+00 2.55e+02 7.67e+02 0.8 3.59e+02 - 2.06e-02 8.24e-03f 2\n", + " 29r 0.0000000e+00 3.58e+02 5.95e+01 0.8 1.21e-01 1.4 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 8.66e+02 2.43e+02 0.8 6.93e+01 - 9.31e-01 4.48e-01f 2\n", + " 31r 0.0000000e+00 7.82e+02 2.67e+02 0.8 5.52e+00 0.9 8.90e-02 9.64e-02h 1\n", + " 32r 0.0000000e+00 6.93e+02 1.87e+02 0.8 2.84e+01 - 5.79e-02 1.48e-01h 1\n", + " 33r 0.0000000e+00 5.58e+02 1.23e+02 0.8 2.39e+01 - 2.97e-01 3.32e-01f 1\n", + " 34r 0.0000000e+00 4.53e+02 2.25e+02 0.8 1.58e+01 - 1.41e-01 2.10e-01f 1\n", + " 35r 0.0000000e+00 4.31e+02 1.86e+02 0.8 1.74e+01 - 2.72e-02 5.15e-02h 1\n", + " 36r 0.0000000e+00 4.28e+02 3.00e+02 0.8 4.39e+01 - 1.73e-03 5.76e-03h 1\n", + " 37r 0.0000000e+00 4.28e+02 2.99e+02 0.8 1.11e+03 - 2.19e-05 2.25e-04h 1\n", + " 38r 0.0000000e+00 4.28e+02 6.92e+02 0.8 2.39e+02 1.3 2.42e-03 1.96e-04f 1\n", + " 39r 0.0000000e+00 4.12e+02 1.12e+04 0.8 1.90e+01 - 7.18e-01 3.76e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.29e+02 2.87e+02 0.8 1.04e+01 - 1.00e+00 1.00e+00f 1\n", + " 41r 0.0000000e+00 4.97e+01 7.12e+02 0.8 5.85e+00 - 5.86e-01 6.18e-01h 1\n", + " 42r 0.0000000e+00 1.60e+00 1.99e+02 0.8 7.12e-01 0.8 1.00e+00 1.00e+00f 1\n", + " 43r 0.0000000e+00 2.18e+01 1.63e+02 0.1 6.04e+01 0.4 1.22e-02 7.09e-03f 1\n", + " 44r 0.0000000e+00 7.21e+03 1.05e+03 0.1 1.64e+02 - 1.83e-01 7.12e-01f 1\n", + " 45r 0.0000000e+00 6.31e+03 7.50e+02 0.1 5.95e+01 - 1.09e-01 1.68e-01f 1\n", + " 46r 0.0000000e+00 6.22e+03 1.41e+03 0.1 9.02e+01 - 8.19e-04 1.38e-02f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 47r 0.0000000e+00 6.22e+03 1.41e+03 0.1 1.27e+02 0.8 1.98e-03 9.14e-04h 1\n", + " 48r 0.0000000e+00 6.21e+03 1.57e+03 0.1 2.55e+02 0.3 1.66e-05 7.85e-04h 1\n", + " 49r 0.0000000e+00 6.18e+03 1.56e+03 0.1 2.15e+01 0.7 2.64e-03 4.99e-03h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 6.18e+03 1.60e+03 0.1 1.55e+02 0.3 2.53e-05 2.61e-04h 1\n", + " 51r 0.0000000e+00 6.18e+03 1.67e+03 0.1 7.60e+01 1.6 1.06e-02 3.63e-04h 1\n", + " 52r 0.0000000e+00 5.80e+03 1.65e+03 0.1 2.59e+01 - 3.10e-02 6.80e-02f 1\n", + " 53r 0.0000000e+00 5.29e+03 1.04e+03 0.1 3.13e+01 - 8.78e-01 6.14e-01f 1\n", + " 54r 0.0000000e+00 2.06e+03 3.00e+02 0.1 3.76e+01 - 7.50e-01 1.00e+00h 1\n", + " 55r 0.0000000e+00 5.02e+01 1.17e+02 0.1 1.26e+01 - 1.00e+00 1.00e+00h 1\n", + " 56r 0.0000000e+00 4.11e+01 1.08e+02 0.1 4.23e+00 - 2.42e-01 1.84e-01h 1\n", + " 57r 0.0000000e+00 2.12e+01 5.27e+01 0.1 1.15e+00 - 7.37e-01 8.32e-01h 1\n", + " 58r 0.0000000e+00 4.74e+01 3.85e+01 0.1 1.60e+00 - 9.93e-01 1.00e+00f 1\n", + " 59r 0.0000000e+00 1.17e+01 3.25e+01 0.1 1.40e+00 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 1.21e+03 4.46e+01 -0.6 5.97e+01 - 7.60e-01 6.94e-01f 1\n", + " 61r 0.0000000e+00 1.54e+03 4.60e+00 -0.6 9.23e+01 - 1.00e+00 1.00e+00f 1\n", + " 62r 0.0000000e+00 1.21e+01 9.28e+00 -0.6 4.59e+01 - 1.00e+00 1.00e+00h 1\n", + " 63r 0.0000000e+00 1.83e+00 9.35e-02 -0.6 2.84e+00 - 1.00e+00 1.00e+00h 1\n", + " 64r 0.0000000e+00 1.11e+03 6.94e+01 -1.3 7.51e+01 - 9.02e-01 9.81e-01f 1\n", + " 65r 0.0000000e+00 7.93e+00 9.52e-01 -1.3 2.38e+01 - 1.00e+00 1.00e+00h 1\n", + " 66r 0.0000000e+00 1.78e+00 1.07e-01 -1.3 8.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 67r 0.0000000e+00 2.18e-01 1.01e-05 -1.3 3.94e-03 - 1.00e+00 1.00e+00h 1\n", + " 68r 0.0000000e+00 1.15e+03 4.78e+01 -4.5 7.86e+01 - 7.94e-01 8.05e-01f 1\n", + " 69r 0.0000000e+00 5.20e+02 1.43e+02 -4.5 2.20e+01 - 9.21e-01 5.55e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 2.62e+02 4.30e+02 -4.5 1.21e-02 1.1 9.09e-01 4.96e-01h 1\n", + " 71r 0.0000000e+00 6.29e+01 1.51e+02 -4.5 1.25e-02 0.6 9.00e-01 7.60e-01h 1\n", + " 72r 0.0000000e+00 9.72e+00 5.07e+01 -4.5 5.71e-02 0.2 9.11e-01 8.46e-01h 1\n", + " 73r 0.0000000e+00 2.40e-01 8.98e-01 -4.5 1.58e-01 -0.3 1.00e+00 9.91e-01h 1\n", + " 74r 0.0000000e+00 3.60e-01 1.74e+02 -4.5 3.96e+03 - 6.95e-03 2.59e-03f 1\n", + " 75r 0.0000000e+00 8.17e-01 3.02e+02 -4.5 9.81e+00 - 7.96e-02 1.55e-02h 1\n", + " 76r 0.0000000e+00 2.96e+02 1.34e+03 -4.5 3.56e+00 - 9.74e-02 3.29e-01h 1\n", + " 77r 0.0000000e+00 2.24e+02 1.38e+03 -4.5 2.48e-02 -0.8 1.00e+00 2.45e-01h 1\n", + " 78r 0.0000000e+00 1.29e+03 6.57e+02 -4.5 1.82e+00 - 6.97e-01 1.00e+00h 1\n", + " 79r 0.0000000e+00 2.01e+02 1.01e+02 -4.5 2.12e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 4.78e+00 7.47e-01 -4.5 3.32e-01 - 1.00e+00 1.00e+00h 1\n", + " 81r 0.0000000e+00 2.94e+00 2.75e-02 -4.5 2.59e-01 - 1.00e+00 1.00e+00h 1\n", + " 82r 0.0000000e+00 2.79e-01 2.57e-03 -4.5 2.99e-02 - 1.00e+00 1.00e+00h 1\n", + " 83r 0.0000000e+00 2.79e-01 4.06e-04 -4.5 4.57e-03 - 1.00e+00 1.00e+00h 1\n", + " 84r 0.0000000e+00 2.79e-01 1.25e-07 -4.5 8.34e-05 - 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 5.26e+01 1.09e+01 -6.8 7.12e-01 - 9.31e-01 8.92e-01f 1\n", + " 86r 0.0000000e+00 2.95e+01 4.47e+02 -6.8 1.59e-01 - 7.12e-01 4.40e-01h 1\n", + " 87r 0.0000000e+00 7.70e+00 1.01e+02 -6.8 9.53e-02 - 8.78e-01 7.65e-01h 1\n", + " 88r 0.0000000e+00 3.45e+00 1.42e+02 -6.8 9.16e-02 - 1.00e+00 7.55e-01h 1\n", + " 89r 0.0000000e+00 9.20e-01 4.87e+01 -6.8 1.08e-01 - 8.60e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90r 0.0000000e+00 8.31e-01 1.80e-01 -6.8 1.38e-01 - 1.00e+00 1.00e+00h 1\n", + " 91r 0.0000000e+00 2.83e-01 1.84e-01 -6.8 7.34e-02 - 1.00e+00 1.00e+00h 1\n", + " 92r 0.0000000e+00 2.83e-01 4.21e+02 -6.8 9.27e-01 - 1.19e-01 4.48e-03h 6\n", + " 93r 0.0000000e+00 2.83e-01 1.51e+02 -6.8 9.89e-06 -1.3 1.00e+00 1.03e-01h 1\n", + " 94r 0.0000000e+00 2.83e-01 3.45e+02 -6.8 1.02e+00 - 1.44e-01 2.36e-02h 3\n", + " 95r 0.0000000e+00 2.83e-01 2.09e+01 -6.8 6.98e-03 -1.7 3.75e-02 2.48e-02h 2\n", + " 96r 0.0000000e+00 2.83e-01 7.23e+00 -6.8 5.65e-04 -2.2 9.81e-01 1.00e+00h 1\n", + " 97r 0.0000000e+00 1.20e+01 2.06e+02 -6.8 1.57e+00 - 1.00e+00 3.33e-01h 2\n", + " 98r 0.0000000e+00 1.19e+01 2.37e+01 -6.8 1.56e-02 - 1.00e+00 5.65e-03h 8\n", + " 99r 0.0000000e+00 1.18e+01 2.23e+01 -6.8 1.79e-02 - 1.00e+00 7.81e-03h 8\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 0.0000000e+00 1.18e+01 2.16e+01 -6.8 1.76e-02 - 1.00e+00 1.95e-03h 10\n", + " 101r 0.0000000e+00 1.18e+01 2.14e+01 -6.8 1.76e-02 - 1.00e+00 9.77e-04h 11\n", + " 102r 0.0000000e+00 1.18e+01 2.13e+01 -6.8 1.76e-02 - 1.00e+00 4.88e-04h 12\n", + " 103r 0.0000000e+00 2.90e-01 3.50e-04 -6.8 1.76e-02 - 1.00e+00 1.00e+00h 1\n", + " 104r 0.0000000e+00 7.03e+00 2.14e+02 -6.8 4.02e-01 - 5.84e-01 1.00e+00h 1\n", + " 105r 0.0000000e+00 2.96e-01 5.54e+01 -6.8 7.32e-02 - 2.26e-01 1.00e+00h 1\n", + " 106r 0.0000000e+00 2.96e-01 8.03e-05 -6.8 1.47e-04 -2.7 1.00e+00 1.00e+00h 1\n", + " 107r 0.0000000e+00 2.95e-01 4.46e+01 -6.8 1.04e-01 - 1.00e+00 5.00e-01h 2\n", + " 108r 0.0000000e+00 2.95e-01 1.34e-02 -6.8 1.91e-02 - 1.00e+00 1.00e+00h 1\n", + " 109r 0.0000000e+00 2.94e-01 1.41e-03 -6.8 3.97e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110r 0.0000000e+00 2.94e-01 9.14e-04 -6.8 2.67e-02 - 1.00e+00 1.00e+00h 1\n", + " 111r 0.0000000e+00 2.94e-01 4.70e-05 -6.8 1.04e-03 - 1.00e+00 1.00e+00h 1\n", + " 112r 0.0000000e+00 2.94e-01 1.32e-07 -6.8 7.16e-04 - 1.00e+00 1.00e+00h 1\n", + " 113r 0.0000000e+00 2.94e-01 1.82e-12 -6.8 2.28e-06 - 1.00e+00 1.00e+00h 1\n", + " 114r 0.0000000e+00 9.46e-01 5.08e+00 -9.0 2.12e-01 - 6.64e-01 6.35e-01h 1\n", + " 115r 0.0000000e+00 1.29e+01 9.86e+00 -9.0 5.14e-01 - 7.92e-01 7.53e-01h 1\n", + " 116r 0.0000000e+00 6.76e+00 1.53e+02 -9.0 2.57e-01 - 8.31e-01 6.76e-01h 1\n", + " 117r 0.0000000e+00 8.96e+00 2.11e+00 -9.0 1.62e-01 - 1.00e+00 1.00e+00h 1\n", + " 118r 0.0000000e+00 8.94e-01 8.15e-01 -9.0 8.76e-02 - 1.00e+00 1.00e+00h 1\n", + " 119r 0.0000000e+00 5.50e-01 2.30e-02 -9.0 1.13e-01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120r 0.0000000e+00 2.99e-01 1.49e-04 -9.0 1.27e-02 - 1.00e+00 1.00e+00h 1\n", + " 121r 0.0000000e+00 2.98e-01 2.05e-05 -9.0 1.10e-02 - 1.00e+00 1.00e+00h 1\n", + " 122r 0.0000000e+00 2.98e-01 2.86e-08 -9.0 5.44e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 122\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 4.6276843335396955e-07 4.6276843335396955e-07\n", + "Constraint violation....: 2.9835465732216782e-01 2.9835465732216782e-01\n", + "Complementarity.........: 9.0909090909100423e-10 9.0909090909100423e-10\n", + "Overall NLP error.......: 2.9835465732216782e-01 2.9835465732216782e-01\n", + "\n", + "\n", + "Number of objective function evaluations = 193\n", + "Number of objective gradient evaluations = 3\n", + "Number of equality constraint evaluations = 193\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 125\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 123\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.161\n", + "Total CPU secs in NLP function evaluations = 0.016\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "outputs": [], + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpg07cmjii\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpg07cmjii\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 155\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.74e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1r 0.0000000e+00 3.74e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 3.17e-07R 3\n", + " 2r 0.0000000e+00 6.21e+04 1.21e+03 3.6 3.74e+06 - 3.68e-03 3.56e-04f 1\n", + " 3r 0.0000000e+00 5.77e+04 1.01e+05 3.6 5.16e+05 - 8.85e-02 4.63e-03f 1\n", + " 4r 0.0000000e+00 5.27e+04 7.54e+04 3.6 3.55e+03 - 2.53e-01 9.39e-02f 1\n", + " 5r 0.0000000e+00 6.46e+04 1.25e+05 3.6 1.62e+02 - 6.86e-01 3.91e-01f 1\n", + " 6r 0.0000000e+00 4.60e+04 2.59e+04 3.6 3.07e+01 - 1.00e+00 7.29e-01f 1\n", + " 7r 0.0000000e+00 1.41e+04 8.03e+03 3.6 3.17e+01 - 1.00e+00 1.00e+00f 1\n", + " 8r 0.0000000e+00 3.34e+04 6.37e+03 2.9 3.71e+01 - 7.68e-01 8.25e-01f 1\n", + " 9r 0.0000000e+00 1.19e+04 7.40e+02 2.9 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 6.30e+03 4.59e+02 2.9 2.35e+01 - 1.00e+00 1.00e+00h 1\n", + " 11r 0.0000000e+00 5.23e+04 5.45e+02 2.2 2.33e+01 - 9.62e-01 9.77e-01f 1\n", + " 12r 0.0000000e+00 7.00e+03 1.04e+02 2.2 2.11e+01 - 1.00e+00 1.00e+00f 1\n", + " 13r 0.0000000e+00 7.13e+02 1.92e+01 2.2 5.17e+00 - 1.00e+00 1.00e+00f 1\n", + " 14r 0.0000000e+00 5.67e+03 7.52e+02 1.5 1.80e+01 - 8.36e-01 9.57e-01f 1\n", + " 15r 0.0000000e+00 1.39e+04 5.79e+02 1.5 7.56e+01 - 7.87e-01 5.50e-01f 1\n", + " 16r 0.0000000e+00 1.86e+04 4.46e+02 1.5 1.21e+01 - 6.13e-01 1.00e+00f 1\n", + " 17r 0.0000000e+00 1.24e+04 2.49e+02 1.5 1.26e+01 - 7.29e-01 1.00e+00f 1\n", + " 18r 0.0000000e+00 8.65e+02 4.42e+01 1.5 9.39e+00 - 1.00e+00 1.00e+00h 1\n", + " 19r 0.0000000e+00 2.73e+02 1.31e+00 1.5 2.73e+00 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 3.72e+03 2.13e+02 0.8 1.88e+01 - 9.33e-01 9.68e-01f 1\n", + " 21r 0.0000000e+00 9.91e+01 1.22e+02 0.8 1.24e-01 2.0 1.00e+00 1.00e+00f 1\n", + " 22r 0.0000000e+00 2.89e+01 1.01e+03 0.8 4.57e-01 1.5 3.88e-01 9.92e-01H 1\n", + " 23r 0.0000000e+00 4.92e+02 1.65e+02 0.8 4.52e-01 1.0 1.00e+00 9.06e-01f 1\n", + " 24r 0.0000000e+00 4.89e+02 3.27e+02 0.8 4.93e-01 1.5 6.74e-01 8.51e-01f 1\n", + " 25r 0.0000000e+00 2.08e+02 7.82e+01 0.8 7.90e-02 2.8 1.00e+00 1.00e+00f 1\n", + " 26r 0.0000000e+00 2.93e+02 1.41e+02 0.8 9.61e-01 2.3 2.45e-01 2.35e-01f 1\n", + " 27r 0.0000000e+00 2.70e+02 7.26e+02 0.8 8.43e-01 1.8 3.36e-01 6.18e-02f 1\n", + " 28r 0.0000000e+00 2.69e+02 7.21e+02 0.8 5.66e+02 - 1.20e-02 4.81e-03f 2\n", + " 29r 0.0000000e+00 4.15e+02 6.03e+01 0.8 1.17e-01 1.4 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 8.56e+02 2.58e+02 0.8 7.00e+01 - 9.49e-01 4.42e-01f 2\n", + " 31r 0.0000000e+00 6.84e+02 2.86e+02 0.8 2.71e+00 0.9 1.79e-01 2.01e-01h 1\n", + " 32r 0.0000000e+00 5.92e+02 1.69e+02 0.8 2.88e+01 - 1.34e-01 3.24e-01f 1\n", + " 33r 0.0000000e+00 4.89e+02 1.45e+02 0.8 1.92e+01 - 1.00e+00 1.00e+00f 1\n", + " 34r 0.0000000e+00 7.71e+00 5.04e+01 0.8 1.11e+00 - 1.00e+00 1.00e+00h 1\n", + " 35r 0.0000000e+00 8.63e+03 3.42e+01 -0.6 2.52e+01 - 6.33e-01 6.26e-01f 1\n", + " 36r 0.0000000e+00 5.46e+03 5.26e+02 -0.6 1.02e+00 0.4 6.69e-01 3.70e-01f 1\n", + " 37r 0.0000000e+00 2.30e+03 1.84e+02 -0.6 6.65e-01 0.8 6.29e-01 5.80e-01f 1\n", + " 38r 0.0000000e+00 9.77e+02 7.18e+01 -0.6 1.85e+00 0.4 4.96e-01 6.05e-01f 1\n", + " 39r 0.0000000e+00 7.39e+02 5.97e+01 -0.6 2.45e+00 -0.1 4.52e-01 4.94e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 8.88e+02 1.40e+02 -0.6 7.33e+00 -0.6 6.79e-01 3.09e-01h 1\n", + " 41r 0.0000000e+00 1.61e+01 1.29e+01 -0.6 3.68e-01 0.7 1.00e+00 1.00e+00h 1\n", + " 42r 0.0000000e+00 6.47e+01 6.22e+00 -0.6 9.57e-01 0.3 1.00e+00 1.00e+00h 1\n", + " 43r 0.0000000e+00 5.42e+02 5.88e+00 -0.6 3.02e+00 -0.2 1.00e+00 1.00e+00h 1\n", + " 44r 0.0000000e+00 1.31e+03 5.88e+01 -0.6 9.54e+00 -0.7 5.38e-01 4.31e-01h 1\n", + " 45r 0.0000000e+00 1.41e+03 2.73e+02 -0.6 1.19e+02 - 1.87e-01 1.21e-01h 1\n", + " 46r 0.0000000e+00 1.08e+03 3.24e+02 -0.6 1.37e+02 - 6.36e-01 4.65e-01f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 47r 0.0000000e+00 6.96e+02 2.77e+02 -0.6 8.41e+00 - 4.25e-01 3.72e-01h 1\n", + " 48r 0.0000000e+00 1.45e+02 1.84e+02 -0.6 8.64e+00 - 5.45e-01 7.92e-01h 1\n", + " 49r 0.0000000e+00 7.13e+01 3.91e+02 -0.6 2.50e+00 - 7.16e-01 5.13e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 4.36e+00 1.14e+02 -0.6 2.79e+00 - 1.00e+00 1.00e+00f 1\n", + " 51r 0.0000000e+00 6.03e-01 2.36e+01 -0.6 8.61e-01 - 1.00e+00 1.00e+00h 1\n", + " 52r 0.0000000e+00 6.61e-01 4.55e+00 -0.6 2.56e-01 - 1.00e+00 1.00e+00h 1\n", + " 53r 0.0000000e+00 1.10e+03 6.90e+01 -1.3 7.52e+01 - 9.02e-01 9.81e-01f 1\n", + " 54r 0.0000000e+00 8.00e+00 8.01e-01 -1.3 2.37e+01 - 1.00e+00 1.00e+00h 1\n", + " 55r 0.0000000e+00 1.78e+00 1.07e-01 -1.3 8.16e-01 - 1.00e+00 1.00e+00h 1\n", + " 56r 0.0000000e+00 2.18e-01 5.40e-06 -1.3 3.90e-03 - 1.00e+00 1.00e+00h 1\n", + " 57r 0.0000000e+00 1.15e+03 4.77e+01 -4.5 7.87e+01 - 7.94e-01 8.05e-01f 1\n", + " 58r 0.0000000e+00 5.17e+02 1.43e+02 -4.5 2.20e+01 - 9.21e-01 5.56e-01h 1\n", + " 59r 0.0000000e+00 2.84e+02 5.22e+02 -4.5 1.42e-01 -1.2 9.08e-01 4.51e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 5.10e+01 1.24e+02 -4.5 2.35e-01 -1.6 9.14e-01 8.21e-01h 1\n", + " 61r 0.0000000e+00 5.05e+01 4.54e+02 -4.5 4.49e+02 - 1.00e+00 2.18e-02h 1\n", + " 62r 0.0000000e+00 1.39e+03 2.01e+02 -4.5 3.30e+00 - 1.00e+00 9.24e-01h 1\n", + " 63r 0.0000000e+00 2.91e+02 7.48e+01 -4.5 1.78e-01 - 1.00e+00 7.97e-01h 1\n", + " 64r 0.0000000e+00 4.07e+00 2.17e+01 -4.5 7.87e-02 - 1.00e+00 1.00e+00h 1\n", + " 65r 0.0000000e+00 3.04e+00 2.05e+02 -4.5 5.95e-01 - 1.00e+00 2.50e-01h 3\n", + " 66r 0.0000000e+00 2.27e+00 1.18e+02 -4.5 5.27e-01 - 1.00e+00 2.50e-01h 3\n", + " 67r 0.0000000e+00 2.00e+00 6.21e+01 -4.5 3.35e-01 - 1.00e+00 5.00e-01h 2\n", + " 68r 0.0000000e+00 9.09e-01 8.92e-02 -4.5 1.44e-01 - 1.00e+00 1.00e+00h 1\n", + " 69r 0.0000000e+00 2.78e-01 2.22e-02 -4.5 6.01e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 2.78e-01 9.38e-05 -4.5 1.31e-03 - 1.00e+00 1.00e+00h 1\n", + " 71r 0.0000000e+00 5.15e+01 1.10e+01 -6.8 7.08e-01 - 9.31e-01 8.92e-01h 1\n", + " 72r 0.0000000e+00 2.90e+01 4.50e+02 -6.8 1.50e-01 - 7.13e-01 4.39e-01h 1\n", + " 73r 0.0000000e+00 7.89e+00 1.01e+02 -6.8 8.85e-02 - 8.77e-01 7.65e-01h 1\n", + " 74r 0.0000000e+00 2.97e+00 1.42e+02 -6.8 9.08e-02 - 1.00e+00 7.58e-01h 1\n", + " 75r 0.0000000e+00 8.82e-01 4.89e+01 -6.8 1.11e-01 - 8.59e-01 1.00e+00h 1\n", + " 76r 0.0000000e+00 7.58e-01 1.53e-01 -6.8 1.32e-01 - 1.00e+00 1.00e+00h 1\n", + " 77r 0.0000000e+00 2.82e-01 2.05e-01 -6.8 7.96e-02 - 1.00e+00 1.00e+00h 1\n", + " 78r 0.0000000e+00 2.82e-01 6.98e+01 -6.8 5.00e-01 - 2.24e-01 2.59e-01H 1\n", + " 79r 0.0000000e+00 2.82e-01 2.94e+02 -6.8 1.59e-01 - 1.00e+00 1.67e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 2.81e-01 1.89e+02 -6.8 4.85e-01 - 8.32e-02 9.31e-02f 2\n", + " 81r 0.0000000e+00 2.81e-01 5.14e+02 -6.8 7.87e-04 -2.1 4.98e-01 7.44e-01h 1\n", + " 82r 0.0000000e+00 2.81e-01 9.19e+02 -6.8 2.22e-04 -2.6 1.00e+00 2.63e-01h 1\n", + " 83r 0.0000000e+00 2.81e-01 1.65e-02 -6.8 9.95e-04 -3.1 1.00e+00 1.00e+00f 1\n", + " 84r 0.0000000e+00 7.23e+00 1.63e-01 -6.8 4.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 85r 0.0000000e+00 2.87e-01 2.33e-04 -6.8 9.28e-03 - 1.00e+00 1.00e+00h 1\n", + " 86r 0.0000000e+00 2.87e-01 1.97e+00 -6.8 5.56e-01 - 1.00e+00 1.22e-04h 14\n", + " 87r 0.0000000e+00 2.87e-01 2.46e+00 -6.8 5.00e-01 - 1.00e+00 1.22e-04h 14\n", + " 88r 0.0000000e+00 2.87e-01 2.58e+00 -6.8 4.78e-01 - 1.00e+00 1.22e-04h 14\n", + " 89r 0.0000000e+00 2.87e-01 2.62e+00 -6.8 4.70e-01 - 1.00e+00 1.22e-04h 14\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.67e-01 - 1.00e+00 1.22e-04h 14\n", + " 91r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.66e-01 - 1.00e+00 1.22e-04h 14\n", + " 92r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 93r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 94r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 95r 0.0000000e+00 2.87e-01 2.64e+00 -6.8 4.65e-01 - 1.00e+00 1.22e-04h 14\n", + " 96r 0.0000000e+00 9.42e+00 1.88e-02 -6.8 4.65e-01 - 1.00e+00 1.00e+00w 1\n", + " 97r 0.0000000e+00 2.93e-01 1.19e-06 -6.8 8.82e-04 - 1.00e+00 1.00e+00w 1\n", + " 98r 0.0000000e+00 2.93e-01 5.78e-06 -6.8 2.07e-03 - 1.00e+00 1.00e+00w 1\n", + " 99r 0.0000000e+00 2.93e-01 2.04e-11 -6.8 4.54e-06 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 0.0000000e+00 7.74e-01 4.78e+00 -9.0 2.09e-01 - 6.64e-01 6.37e-01h 1\n", + " 101r 0.0000000e+00 8.46e+00 3.40e+01 -9.0 3.17e-01 - 9.10e-01 7.63e-01h 1\n", + " 102r 0.0000000e+00 4.04e+00 2.19e+02 -9.0 2.21e-01 - 8.62e-01 6.33e-01h 1\n", + " 103r 0.0000000e+00 7.03e+00 1.45e+00 -9.0 1.41e-01 - 1.00e+00 1.00e+00h 1\n", + " 104r 0.0000000e+00 7.21e-01 5.48e-01 -9.0 9.46e-02 - 1.00e+00 1.00e+00h 1\n", + " 105r 0.0000000e+00 2.97e-01 1.72e-02 -9.0 7.60e-02 - 1.00e+00 1.00e+00h 1\n", + " 106r 0.0000000e+00 2.97e-01 6.61e-05 -9.0 2.35e-02 - 1.00e+00 1.00e+00h 1\n", + " 107r 0.0000000e+00 2.97e-01 1.83e-06 -9.0 1.21e-03 - 1.00e+00 1.00e+00h 1\n", + " 108r 0.0000000e+00 2.97e-01 3.43e-08 -9.0 2.97e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 108\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 3.0151134107357916e-07 3.0151134107357916e-07\n", + "Constraint violation....: 2.9731578903766509e-01 2.9731578903766509e-01\n", + "Complementarity.........: 9.0909090909099699e-10 9.0909090909099699e-10\n", + "Overall NLP error.......: 2.9731578903766509e-01 2.9731578903766509e-01\n", + "\n", + "\n", + "Number of objective function evaluations = 271\n", + "Number of objective gradient evaluations = 3\n", + "Number of equality constraint evaluations = 271\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 111\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 109\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.155\n", + "Total CPU secs in NLP function evaluations = 0.015\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate Liq mole / second 0.30001 2.0000e-05 0.29609 4.7359e-12 0.22506 1.0000e-08 0.30007 8.0134e-09 8.0151e-09 1.0000e-08 0.30007 2.0077e-09\n", + " Total Molar Flowrate Vap mole / second 4.0000e-05 0.32002 0.32272 0.61696 0.075008 2.0137e-10 1.0000e-08 1.5056e-10 1.3399e-10 1.9913e-08 1.0000e-08 4.0429e-11\n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 3.3332e-05 0.50000 0.00012935 5.9851e-05 1.0000e-20 1.0000e-20 1.0000e-20 0.0016277 0.0017605 1.0000e-20 1.0000e-20 0.0038222\n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.99997 0.50000 0.99987 0.99994 1.0000 1.0000 1.0000 0.99837 0.99824 1.0000 1.0000 0.99618\n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.25000 3.1248e-05 5.2698e-06 6.4834e-05 1.0000e-20 1.0000e-20 1.0000e-20 0.00017956 0.00019422 1.0000e-20 1.0000e-20 0.00042167\n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.25000 3.1248e-05 0.012327 0.48630 1.0000 0.037785 0.037785 0.037723 0.037718 0.51680 0.51680 0.037640\n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.25000 0.93744 0.92592 0.48184 1.3527e-09 0.49388 0.49388 0.49395 0.49398 0.24801 0.24801 0.49387\n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.25000 0.062496 0.061748 0.031794 1.2842e-09 0.46834 0.46834 0.46815 0.46810 0.23519 0.23519 0.46807\n", + " Temperature kelvin 303.20 303.20 300.45 600.00 664.03 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "source": [ + "m.fs.report()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 225939.23444372677\n" + ] + } + ], + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 2575.4 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 0.30007 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.037785 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.49388 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.46834 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.30007 \n", + " flow_mol_phase Vap mole / second - 1.9913e-08 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 1.0000e-20 1.0000e-20 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 1.0000 1.0000 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 1.0000e-20 1.0000e-20 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.51680 0.51680 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.24801 0.24801 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.23519 0.23519 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 1.934999854274726e-20\n" + ] + } + ], + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate Liq mole / second 0.22506 1.0000e-08 \n", + "Total Molar Flowrate Vap mole / second 0.075008 2.0137e-10 \n", + "Total Mole Fraction ('Liq', 'benzene') dimensionless 1.0000e-20 1.0000e-20 \n", + "Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 1.0000 \n", + "Total Mole Fraction ('Vap', 'benzene') dimensionless 1.0000e-20 1.0000e-20 \n", + "Total Mole Fraction ('Vap', 'toluene') dimensionless 1.0000 0.037785 \n", + "Total Mole Fraction ('Vap', 'hydrogen') dimensionless 1.3527e-09 0.49388 \n", + "Total Mole Fraction ('Vap', 'methane') dimensionless 1.2842e-09 0.46834 \n", + "Temperature kelvin 664.03 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "outputs": [], + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "outputs": [], + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "outputs": [], + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "outputs": [], + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "outputs": [], + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpl0wqmn_f\\unknown.14248.22376.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpl0wqmn_f\\unknown.14248.22376.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 159\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 2.2593923e+05 4.10e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 2.2592658e+05 4.10e+04 6.94e+00 -1.0 2.26e+06 - 1.24e-06 1.27e-06f 1\n", + " 2 2.2592558e+05 4.10e+04 3.83e+02 -1.0 1.09e+07 - 2.51e-06 1.27e-08f 1\n", + " 3 2.2575143e+05 4.10e+04 9.02e+03 -1.0 2.27e+09 - 2.63e-07 1.12e-08f 1\n", + " 4 2.1959194e+05 4.10e+04 5.77e+03 -1.0 2.25e+09 - 2.72e-07 3.98e-07f 1\n", + " 5 1.8296150e+05 3.46e+05 1.20e+05 -1.0 1.14e+09 - 7.70e-07 4.70e-06f 1\n", + " 6 1.8296150e+05 3.45e+05 4.95e+07 -1.0 1.99e+04 6.0 1.10e-01 2.49e-03h 1\n", + " 7 1.8308684e+05 3.45e+05 1.07e+10 -1.0 1.59e+07 - 4.38e-11 2.97e-05h 1\n", + " 8 1.8308686e+05 3.45e+05 1.07e+10 -1.0 3.47e+04 5.5 2.57e-08 1.27e-06f 2\n", + " 9 1.8308346e+05 3.45e+05 1.07e+10 -1.0 2.33e+06 - 1.28e-06 1.28e-06f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 1.8308346e+05 3.45e+05 9.99e+02 5.5 0.00e+00 - 0.00e+00 6.41e-09R 2\n", + " 11r 1.8308366e+05 3.44e+05 6.06e+03 5.5 3.59e+08 - 9.52e-05 2.75e-06f 1\n", + " 12r 1.8308341e+05 3.96e+04 6.44e+03 3.4 3.13e+08 - 4.75e-04 1.01e-03f 1\n", + " 13 1.8245986e+05 3.96e+04 3.21e+03 -1.0 9.17e+06 - 1.24e-04 1.01e-05f 1\n", + " 14 1.8245424e+05 3.96e+04 4.69e+06 -1.0 8.13e+06 - 1.38e-04 1.01e-07f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 15 1.8245406e+05 3.96e+04 8.01e+11 -1.0 5.70e+07 - 3.66e-04 1.06e-09f 2\n", + " 16 1.8163981e+05 3.96e+04 1.52e+12 -1.0 5.47e+08 - 2.78e-05 1.46e-05f 1\n", + " 17r 1.8163981e+05 3.96e+04 9.99e+02 4.6 0.00e+00 - 0.00e+00 1.32e-12R 2\n", + " 18r 1.8164024e+05 5.96e+04 6.63e+04 4.6 3.30e+07 - 1.77e-02 1.18e-04f 1\n", + " 19r 1.8164102e+05 4.78e+04 6.11e+04 3.2 1.72e+06 - 1.38e-01 1.86e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 1.8164265e+05 4.73e+04 2.42e+04 3.2 2.06e+06 - 6.74e-01 1.03e-02f 1\n", + " 21r 1.8163776e+05 5.59e+04 1.44e+04 3.2 1.58e+03 - 4.29e-01 4.00e-01f 1\n", + " 22r 1.8168500e+05 4.59e+04 2.12e+03 3.2 6.14e+02 - 9.01e-01 8.37e-01f 1\n", + " 23r 1.8167353e+05 7.43e+04 2.27e+03 3.2 1.36e+02 - 3.19e-01 3.02e-01f 1\n", + " 24r 1.8153947e+05 5.07e+04 1.27e+04 3.2 6.53e+01 - 7.65e-01 1.00e+00f 1\n", + " 25r 1.8153947e+05 4.53e+04 1.69e+04 3.2 1.56e+01 4.0 1.07e-01 1.08e-01h 1\n", + " 26r 1.8153947e+05 2.41e+04 6.04e+04 3.2 1.81e+01 3.5 8.20e-01 1.00e+00f 1\n", + " 27 3.9962752e+04 2.41e+04 8.65e+01 -1.0 1.51e+07 - 1.07e-03 1.07e-03f 1\n", + " 28 1.7595823e+04 2.41e+04 1.10e+02 -1.0 2.01e+06 - 8.21e-03 1.19e-03f 1\n", + " 29 -1.6176446e+04 2.40e+04 4.65e+02 -1.0 1.41e+06 - 6.16e-03 4.06e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30 -1.6503845e+04 2.40e+04 4.67e+02 -1.0 1.60e+05 - 5.34e-02 4.11e-04f 1\n", + " 31 -1.6103557e+04 2.39e+04 1.51e+04 -1.0 5.35e+04 - 6.91e-02 1.53e-03h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 32 -1.3109479e+04 2.37e+04 3.61e+04 -1.0 5.32e+04 - 1.16e-01 1.14e-02h 3\n", + " 33 -9.8778958e+03 2.34e+04 8.31e+04 -1.0 5.10e+04 - 2.78e-01 1.32e-02h 3\n", + " 34 -6.1943183e+03 2.30e+04 1.45e+05 -1.0 4.89e+04 - 5.07e-01 1.61e-02h 3\n", + " 35 -1.6595473e+03 2.25e+04 1.62e+05 -1.0 4.68e+04 - 3.19e-01 2.13e-02h 3\n", + " 36 5.4794139e+03 2.18e+04 1.85e+05 -1.0 4.46e+04 - 6.87e-01 3.60e-02h 3\n", + " 37 1.6365098e+04 2.05e+04 1.79e+05 -1.0 4.17e+04 - 3.54e-01 6.02e-02h 3\n", + " 38 2.7740530e+04 1.92e+04 1.68e+05 -1.0 3.80e+04 - 2.00e-01 7.01e-02h 3\n", + " 39 3.9763721e+04 1.78e+04 1.56e+05 -1.0 3.48e+04 - 2.45e-01 8.02e-02h 3\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40 5.2469134e+04 1.64e+04 1.44e+05 -1.0 3.21e+04 - 3.86e-01 9.05e-02h 3\n", + " 41 6.5791945e+04 1.49e+04 1.34e+05 -1.0 2.96e+04 - 6.07e-01 1.01e-01h 3\n", + " 42 1.2096642e+05 1.17e+04 8.09e+04 -1.0 2.75e+04 - 8.69e-01 4.43e-01w 1\n", + " 43 1.3345225e+05 1.02e+04 9.69e+04 -1.0 2.10e+04 - 9.90e-01 1.33e-01w 1\n", + " 44 1.3364425e+05 1.02e+04 1.48e+05 -1.0 2.14e+04 - 1.00e+00 2.24e-03w 1\n", + " 45 7.9585562e+04 1.35e+04 1.27e+05 -1.0 2.14e+04 - 8.69e-01 1.11e-01h 2\n", + " 46 9.2643927e+04 1.22e+04 1.21e+05 -1.0 2.69e+04 - 9.90e-01 1.12e-01h 3\n", + " 47 1.1662879e+05 1.01e+04 1.01e+05 -1.0 2.65e+04 - 1.00e+00 2.21e-01h 2\n", + " 48 1.5635635e+05 6.66e+03 7.23e+04 -1.0 2.30e+04 - 1.00e+00 4.07e-01H 1\n", + " 49 1.5677484e+05 6.62e+03 9.35e+04 -1.0 1.77e+04 - 1.00e+00 6.00e-03h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50 1.5677903e+05 6.62e+03 9.06e+07 -1.0 1.77e+04 - 1.00e+00 6.03e-05h 1\n", + " 51r 1.5677903e+05 6.62e+03 1.00e+03 3.8 0.00e+00 - 0.00e+00 3.01e-07R 2\n", + " 52r 1.5677921e+05 2.60e+03 1.79e+03 3.8 6.62e+06 - 1.08e-02 9.90e-04f 1\n", + " 53 1.5639242e+05 2.60e+03 1.00e+02 -1.0 1.25e+05 - 5.02e-02 4.91e-04f 1\n", + " 54 1.5638540e+05 2.58e+03 7.78e+02 -1.0 1.53e+04 - 3.61e-01 7.65e-03h 1\n", + " 55 1.5639044e+05 2.58e+03 3.43e+06 -1.0 1.52e+04 - 7.08e-01 7.69e-05h 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 56r 1.5639044e+05 2.58e+03 1.00e+03 3.4 0.00e+00 - 0.00e+00 3.85e-07R 2\n", + " 57r 1.5639078e+05 7.01e+02 9.95e+02 3.4 2.58e+06 - 5.78e-03 9.91e-04f 1\n", + " 58 1.5614585e+05 7.00e+02 1.38e+02 -1.0 9.14e+04 - 6.54e-02 4.74e-04f 1\n", + " 59 1.5624013e+05 6.99e+02 4.69e+03 -1.0 1.57e+04 - 5.04e-01 2.61e-03h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60 1.5624202e+05 6.99e+02 1.47e+08 -1.0 1.57e+04 - 8.22e-01 2.62e-05h 1\n", + " 61r 1.5624202e+05 6.99e+02 1.00e+03 2.8 0.00e+00 - 0.00e+00 1.31e-07R 2\n", + " 62r 1.5624284e+05 1.84e+02 9.98e+02 2.8 6.99e+05 - 2.70e-03 9.90e-04f 1\n", + " 63 1.5604488e+05 1.84e+02 1.65e+02 -1.0 7.47e+04 - 7.78e-02 4.95e-04f 1\n", + " 64 1.5606175e+05 1.84e+02 1.65e+05 -1.0 1.59e+04 - 5.42e-01 3.40e-04h 1\n", + " 65r 1.5606175e+05 1.84e+02 1.00e+03 2.3 0.00e+00 - 0.00e+00 4.26e-07R 4\n", + " 66r 1.5606221e+05 4.72e+01 4.65e+03 2.3 1.84e+05 - 3.00e-01 9.90e-04f 1\n", + " 67 1.5598771e+05 4.72e+01 4.39e+02 -1.0 6.50e+04 - 8.77e-02 2.22e-04f 1\n", + " 68r 1.5598771e+05 4.72e+01 9.99e+02 1.7 0.00e+00 - 0.00e+00 2.77e-07R 4\n", + " 69r 1.5598853e+05 1.22e+01 1.33e+03 1.7 4.72e+04 - 3.27e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70 1.5594804e+05 1.22e+01 7.89e+02 -1.0 6.09e+04 - 9.21e-02 1.30e-04f 1\n", + " 71r 1.5594804e+05 1.22e+01 9.99e+02 1.1 0.00e+00 - 0.00e+00 3.24e-07R 3\n", + " 72r 1.5594931e+05 5.34e+01 9.49e+02 1.1 1.22e+04 - 1.28e-01 9.90e-04f 1\n", + " 73r 1.5602328e+05 8.38e+03 8.47e+02 1.1 1.82e+02 - 3.97e-01 1.18e-01f 1\n", + " 74r 1.5611223e+05 5.32e+03 5.09e+02 1.1 1.27e+02 - 4.87e-01 3.88e-01f 1\n", + " 75r 1.5611538e+05 4.46e+03 9.27e+02 1.1 4.35e+01 - 3.30e-01 2.08e-01f 1\n", + " 76r 1.5618738e+05 4.27e+03 3.31e+02 1.1 6.22e+01 - 8.72e-01 5.98e-01f 1\n", + " 77r 1.5626949e+05 2.10e+04 5.81e+03 1.1 2.66e+02 - 6.87e-01 1.00e+00f 1\n", + " 78r 1.5626950e+05 9.45e+02 1.67e+03 1.1 2.44e+00 0.0 9.93e-01 9.56e-01h 1\n", + " 79r 1.5633952e+05 1.55e+03 6.08e+02 1.1 7.00e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 1.5642050e+05 1.38e+02 4.09e+01 1.1 1.25e+01 - 1.00e+00 1.00e+00h 1\n", + " 81r 1.5640166e+05 1.18e+00 1.13e+00 1.1 2.52e+00 - 1.00e+00 1.00e+00h 1\n", + " 82 1.4211718e+05 4.18e+02 7.70e+02 -1.0 7.62e+05 - 5.86e-03 2.54e-03f 1\n", + " 83r 1.4211718e+05 4.18e+02 9.99e+02 2.6 0.00e+00 - 0.00e+00 4.73e-07R 15\n", + " 84r 1.4211760e+05 9.63e+01 7.10e+03 2.6 4.18e+05 - 2.71e-02 9.90e-04f 1\n", + " 85 1.4189541e+05 9.64e+01 3.92e+02 -1.0 3.81e+05 - 1.62e-02 7.48e-05f 1\n", + " 86 1.4037132e+05 2.61e+03 1.06e+03 -1.0 1.60e+04 - 3.64e-02 1.33e-02f 1\n", + " 87 1.4037496e+05 2.61e+03 1.03e+06 -1.0 2.99e+04 - 9.60e-02 1.34e-04h 1\n", + " 88r 1.4037496e+05 2.61e+03 1.00e+03 3.4 0.00e+00 - 0.00e+00 3.35e-07R 3\n", + " 89r 1.4037548e+05 1.23e+03 1.25e+04 3.4 2.61e+06 - 2.16e-02 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90 1.3159180e+05 1.24e+03 1.40e+01 -1.0 1.15e+06 - 1.26e-02 8.35e-04f 1\n", + " 91 1.3048033e+05 1.24e+03 5.90e+01 -1.0 5.18e+04 - 2.81e-02 2.55e-03f 1\n", + " 92 1.3047951e+05 1.24e+03 2.51e+05 -1.0 3.24e+04 - 1.03e-01 2.56e-05f 1\n", + " 93r 1.3047951e+05 1.24e+03 1.00e+03 3.1 0.00e+00 - 0.00e+00 1.28e-07R 2\n", + " 94r 1.3047961e+05 3.22e+02 7.99e+03 3.1 1.24e+06 - 1.28e-01 9.91e-04f 1\n", + " 95 1.2799595e+05 3.22e+02 3.48e+01 -1.0 2.84e+05 - 2.91e-02 8.14e-04f 1\n", + " 96 1.2798856e+05 3.21e+02 2.37e+03 -1.0 3.80e+04 - 8.68e-02 7.83e-04f 1\n", + " 97r 1.2798856e+05 3.21e+02 1.00e+03 2.5 0.00e+00 - 0.00e+00 4.90e-07R 5\n", + " 98r 1.2798821e+05 8.75e+01 6.36e+03 2.5 3.21e+05 - 3.92e-01 9.90e-04f 1\n", + " 99 1.2802319e+05 8.74e+01 1.07e+04 -1.0 4.00e+04 - 1.87e-01 4.16e-04h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 1.2802319e+05 8.74e+01 1.00e+03 1.9 0.00e+00 - 0.00e+00 2.60e-07R 5\n", + " 101r 1.2802286e+05 2.25e+01 1.59e+03 1.9 8.74e+04 - 3.57e-01 9.90e-04f 1\n", + " 102 1.2803524e+05 2.24e+01 3.21e+05 -1.0 4.04e+04 - 3.46e-01 1.15e-04h 1\n", + " 103r 1.2803524e+05 2.24e+01 1.00e+03 1.4 0.00e+00 - 0.00e+00 2.87e-07R 3\n", + " 104r 1.2803522e+05 5.73e+00 9.93e+02 1.4 2.24e+04 - 3.75e-01 9.90e-04f 1\n", + " 105 1.2801361e+05 5.73e+00 1.41e+03 -1.0 5.87e+04 - 3.71e-02 2.95e-05f 1\n", + " 106r 1.2801361e+05 5.73e+00 1.00e+03 0.8 0.00e+00 - 0.00e+00 1.48e-07R 2\n", + " 107r 1.2801478e+05 2.68e+00 9.89e+02 0.8 5.73e+03 - 8.71e-02 9.90e-04f 1\n", + " 108 1.2800949e+05 2.68e+00 5.60e+03 -1.0 5.63e+04 - 3.78e-02 7.54e-06f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 109r 1.2800949e+05 2.68e+00 1.00e+03 0.4 0.00e+00 - 0.00e+00 3.77e-08R 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110r 1.2801166e+05 3.81e+00 9.93e+02 0.4 2.68e+03 - 3.82e-02 9.90e-04f 1\n", + " 111r 1.2802445e+05 6.14e+02 9.64e+02 0.4 3.09e+02 - 2.66e-02 2.94e-02f 1\n", + " 112r 1.2806075e+05 1.08e+03 8.98e+02 0.4 1.58e+02 - 2.79e-01 5.62e-02f 1\n", + " 113r 1.2831404e+05 1.07e+03 6.34e+02 0.4 1.43e+02 - 7.40e-01 3.03e-01f 1\n", + " 114r 1.2886030e+05 3.98e+03 2.01e+02 0.4 5.86e+01 - 9.64e-01 8.55e-01f 1\n", + " 115r 1.2885846e+05 5.59e+03 3.81e+03 0.4 1.76e+01 -2.0 7.49e-01 9.89e-01F 1\n", + " 116r 1.2885837e+05 5.02e+03 1.59e+03 0.4 3.19e+01 -1.6 1.26e-01 1.01e-01h 1\n", + " 117r 1.2875688e+05 7.27e+03 8.69e+03 0.4 1.70e+02 - 9.01e-01 6.08e-01H 1\n", + " 118r 1.2861391e+05 1.91e+03 2.32e+03 0.4 6.76e+01 - 3.09e-01 4.96e-01h 1\n", + " 119r 1.2861391e+05 1.18e+03 1.30e+03 0.4 7.62e-01 0.7 2.63e-01 3.79e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120r 1.2861391e+05 1.50e+01 1.60e+03 0.4 1.12e+00 0.2 1.00e+00 1.00e+00f 1\n", + " 121r 1.2855214e+05 1.41e+03 6.30e+02 0.4 2.14e+02 - 7.06e-01 6.45e-01F 1\n", + " 122r 1.2854036e+05 1.62e+02 2.13e+01 0.4 1.05e+01 - 1.00e+00 1.00e+00f 1\n", + " 123r 1.2854284e+05 6.41e+01 1.88e+00 0.4 5.18e+00 - 1.00e+00 1.00e+00h 1\n", + " 124r 1.2854112e+05 1.24e+00 5.76e-02 0.4 5.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 125 1.2853731e+05 8.25e+00 8.46e+01 -1.0 3.52e+04 - 2.13e-03 1.10e-04f 6\n", + " 126 1.2853574e+05 1.02e+01 1.68e+02 -1.0 3.46e+04 - 3.78e-03 5.51e-05f 7\n", + " 127 1.2853471e+05 1.22e+01 3.97e+02 -1.0 3.51e+04 - 5.15e-03 5.52e-05f 7\n", + " 128 1.2853431e+05 1.41e+01 9.42e+02 -1.0 3.57e+04 - 5.14e-03 5.54e-05f 7\n", + " 129r 1.2853431e+05 1.41e+01 9.99e+02 1.2 0.00e+00 - 0.00e+00 4.36e-07R 14\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130r 1.2853521e+05 3.27e+00 3.14e+03 1.2 1.41e+04 - 6.27e-02 9.90e-04f 1\n", + " 131 1.2034467e+05 2.66e+02 3.47e+02 -1.0 1.47e+06 - 2.72e-03 6.73e-04f 1\n", + " 132 1.2022266e+05 4.31e+03 1.11e+03 -1.0 2.32e+04 - 6.56e-03 2.99e-03f 1\n", + " 133r 1.2022266e+05 4.31e+03 9.99e+02 3.6 0.00e+00 - 0.00e+00 4.67e-07R 7\n", + " 134r 1.2022335e+05 8.51e+03 7.19e+03 3.6 4.31e+06 - 1.68e-02 9.90e-04f 1\n", + " 135r 1.2022365e+05 8.36e+03 7.04e+03 2.2 5.51e+04 - 8.33e-01 1.76e-02f 1\n", + " 136r 1.2028738e+05 2.34e+05 4.43e+03 2.2 4.33e+02 - 5.63e-01 8.32e-01f 1\n", + " 137r 1.2028745e+05 8.35e+04 1.36e+03 2.2 1.19e+01 0.0 5.50e-01 7.32e-01f 1\n", + " 138r 1.2031198e+05 5.29e+04 7.87e+02 2.2 1.46e+02 - 6.30e-01 6.77e-01f 1\n", + " 139r 1.2030652e+05 2.46e+04 1.31e+03 2.2 5.31e+01 - 9.14e-01 8.25e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 1.2030840e+05 2.40e+04 1.29e+03 2.2 3.56e+01 - 1.86e-02 2.50e-02h 1\n", + " 141r 1.2030840e+05 2.36e+04 1.25e+03 2.2 9.18e+00 2.2 3.84e-02 1.35e-02h 1\n", + " 142r 1.2033359e+05 1.95e+04 8.08e+03 2.2 4.55e+01 - 5.22e-01 2.17e-01f 1\n", + " 143r 1.2038554e+05 3.79e+04 1.15e+03 2.2 5.04e+01 - 1.00e+00 1.00e+00f 1\n", + " 144r 1.2036898e+05 1.43e+04 8.09e+02 2.2 2.28e+01 - 1.00e+00 1.00e+00f 1\n", + " 145r 1.2047190e+05 5.00e+03 3.01e+02 2.2 5.23e+01 - 1.00e+00 7.53e-01h 1\n", + " 146r 1.2043452e+05 2.24e+03 2.42e+03 2.2 1.02e+01 - 1.00e+00 5.61e-01f 1\n", + " 147r 1.2041013e+05 4.32e+03 1.02e+03 2.2 1.51e+01 - 1.00e+00 5.72e-01f 1\n", + " 148r 1.2041937e+05 4.84e+02 1.91e+02 2.2 3.50e+00 - 1.00e+00 1.00e+00f 1\n", + " 149 1.1303874e+05 5.57e+03 4.76e+02 -1.0 2.96e+05 - 3.61e-03 2.13e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150 1.1050904e+05 5.53e+03 3.99e+02 -1.0 1.56e+05 - 8.49e-03 1.87e-03f 1\n", + " 151 1.1027960e+05 5.52e+03 4.08e+02 -1.0 7.06e+04 - 1.08e-02 3.88e-04f 1\n", + " 152 1.1027853e+05 5.52e+03 3.78e+05 -1.0 3.54e+04 - 1.88e-02 4.05e-06f 1\n", + " 153r 1.1027853e+05 5.52e+03 1.00e+03 3.7 0.00e+00 - 0.00e+00 2.03e-08R 2\n", + " 154r 1.1027886e+05 6.60e+02 2.29e+03 3.7 5.51e+06 - 3.42e-03 9.93e-04f 1\n", + " 155 1.0759473e+05 6.61e+02 2.40e+01 -1.0 1.36e+06 - 5.20e-03 2.07e-04f 1\n", + " 156 1.0758344e+05 6.61e+02 1.68e+05 -1.0 5.36e+05 - 1.38e-02 2.11e-06f 1\n", + " 157r 1.0758344e+05 6.61e+02 9.99e+02 2.8 0.00e+00 - 0.00e+00 1.06e-08R 2\n", + " 158r 1.0758424e+05 1.76e+02 9.97e+02 2.8 6.61e+05 - 1.95e-03 9.90e-04f 1\n", + " 159 1.0727225e+05 1.76e+02 2.26e+02 -1.0 1.28e+06 - 5.75e-03 2.52e-05f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160 1.0727102e+05 1.76e+02 1.38e+07 -1.0 4.83e+05 - 1.54e-02 2.52e-07f 1\n", + " 161r 1.0727102e+05 1.76e+02 1.00e+03 2.2 0.00e+00 - 0.00e+00 2.10e-09R 2\n", + " 162r 1.0727100e+05 4.49e+01 3.89e+03 2.2 1.76e+05 - 3.33e-01 9.90e-04f 1\n", + " 163 1.0718953e+05 4.49e+01 8.71e+02 -1.0 1.28e+06 - 5.81e-03 6.62e-06f 1\n", + " 164 1.0718937e+05 4.49e+01 2.04e+08 -1.0 4.76e+05 - 1.56e-02 3.31e-08f 2\n", + " 165 1.0719074e+05 4.49e+01 2.41e+12 -1.0 1.39e+07 - 3.27e-04 2.74e-08H 1\n", + " 166r 1.0719074e+05 4.49e+01 1.00e+03 1.7 0.00e+00 - 0.00e+00 1.84e-11R 2\n", + " 167r 1.0719095e+05 1.12e+01 9.90e+02 1.7 4.49e+04 - 1.70e-01 9.90e-04f 1\n", + " 168 1.0717059e+05 1.12e+01 3.49e+03 -1.0 1.27e+06 - 5.83e-03 1.66e-06f 1\n", + " 169r 1.0717059e+05 1.12e+01 9.99e+02 1.0 0.00e+00 - 0.00e+00 8.30e-09R 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 1.0717179e+05 3.98e+00 9.97e+02 1.0 1.12e+04 - 7.26e-02 9.90e-04f 1\n", + " 171 1.0716685e+05 3.98e+00 1.42e+04 -1.0 1.24e+06 - 5.88e-03 4.11e-07f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 172r 1.0716685e+05 3.98e+00 9.99e+02 0.6 0.00e+00 - 0.00e+00 2.06e-09R 2\n", + " 173r 1.0716902e+05 1.22e+01 9.95e+02 0.6 3.98e+03 - 2.60e-02 9.90e-04f 1\n", + " 174r 1.0721151e+05 3.96e+03 9.71e+02 0.6 7.43e+02 - 5.48e-02 2.49e-02f 1\n", + " 175r 1.0733554e+05 8.77e+03 8.92e+02 0.6 7.42e+02 - 2.07e-01 7.93e-02f 1\n", + " 176r 1.0744861e+05 1.81e+04 3.21e+03 0.6 6.39e+02 - 2.76e-01 9.12e-02f 1\n", + " 177r 1.0760156e+05 1.26e+04 2.49e+03 0.6 4.84e+02 - 1.35e-01 1.57e-01f 1\n", + " 178r 1.0759534e+05 1.76e+04 3.00e+03 0.6 8.50e+01 - 2.93e-01 1.80e-01f 1\n", + " 179r 1.0769358e+05 1.54e+04 3.69e+03 0.6 5.91e+01 - 3.85e-01 2.13e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 1.0817736e+05 6.68e+03 3.86e+03 0.6 1.21e+02 - 9.01e-01 5.48e-01f 1\n", + " 181r 1.0810596e+05 6.25e+03 2.22e+03 0.6 6.69e+01 - 3.03e-01 3.61e-01f 1\n", + " 182r 1.0804719e+05 1.30e+03 4.59e+02 0.6 3.46e+01 - 9.90e-01 1.00e+00f 1\n", + " 183r 1.0811628e+05 1.96e+02 1.22e+01 0.6 2.24e+01 - 1.00e+00 1.00e+00f 1\n", + " 184r 1.0810982e+05 6.43e+00 3.18e+00 0.6 9.06e-01 - 1.00e+00 1.00e+00h 1\n", + " 185r 1.0822116e+05 9.78e+02 1.36e+02 -0.8 6.25e+01 - 7.37e-01 6.38e-01f 1\n", + " 186r 1.1108726e+05 1.47e+03 9.49e+01 -0.8 1.17e+03 - 7.44e-01 5.74e-01f 1\n", + " 187r 1.1267097e+05 5.05e+03 8.55e+01 -0.8 5.95e+02 - 1.00e+00 7.56e-01f 1\n", + " 188r 1.1279724e+05 1.61e+03 1.89e+01 -0.8 1.03e+02 - 6.41e-01 6.99e-01h 1\n", + " 189r 1.1300124e+05 7.91e+01 5.00e-01 -0.8 6.37e+01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 1.1300781e+05 1.88e+00 3.19e-02 -0.8 9.42e-01 - 1.00e+00 1.00e+00h 1\n", + " 191r 1.1300781e+05 1.88e+00 9.99e+02 0.3 0.00e+00 - 0.00e+00 1.25e-09R 2\n", + " 192r 1.1300966e+05 4.83e-01 2.16e+04 0.3 1.88e+03 - 8.88e-02 9.90e-04f 1\n", + " 193r 1.1300966e+05 4.83e-01 9.99e+02 -0.3 0.00e+00 - 0.00e+00 1.49e-09R 2\n", + " 194r 1.1301306e+05 1.93e-01 1.24e+04 -0.3 8.04e+02 - 2.20e-01 9.90e-04f 1\n", + " 195r 1.1301306e+05 1.93e-01 9.99e+02 -0.7 0.00e+00 - 0.00e+00 1.56e-09R 2\n", + " 196r 1.1302132e+05 1.93e-01 2.17e+04 -0.7 1.31e+03 - 9.64e-01 1.54e-03f 1\n", + " 197r 1.1823161e+05 6.17e+02 4.80e+02 -0.7 1.34e+03 - 9.89e-01 9.61e-01f 1\n", + " 198r 1.1798536e+05 5.28e+02 6.49e+01 -0.7 5.91e+01 - 7.43e-01 1.00e+00h 1\n", + " 199r 1.1805718e+05 2.99e+02 3.87e+00 -0.7 1.29e+01 - 9.93e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 1.1805876e+05 8.10e+01 1.75e+00 -0.7 3.71e+00 - 1.00e+00 1.00e+00h 1\n", + " 201r 1.1806057e+05 5.70e-01 1.05e-03 -0.7 4.13e-01 - 1.00e+00 1.00e+00h 1\n", + " 202r 1.1811792e+05 3.68e+02 9.69e+00 -1.4 2.10e+01 - 9.31e-01 9.67e-01f 1\n", + " 203r 1.2050787e+05 7.67e+02 6.64e+01 -1.4 1.57e+03 - 6.63e-01 5.35e-01h 1\n", + " 204r 1.2249012e+05 4.59e+02 1.35e+02 -1.4 7.27e+02 - 6.94e-01 1.00e+00h 1\n", + " 205r 1.2248902e+05 6.11e+02 4.56e+01 -1.4 3.65e+00 - 1.00e+00 1.00e+00h 1\n", + " 206r 1.2249445e+05 1.16e+02 6.38e+00 -1.4 7.80e-01 - 1.00e+00 1.00e+00h 1\n", + " 207r 1.2249392e+05 1.06e+00 1.19e-01 -1.4 7.63e-02 - 1.00e+00 1.00e+00h 1\n", + " 208r 1.2249396e+05 1.76e-01 3.39e-05 -1.4 6.38e-03 - 1.00e+00 1.00e+00h 1\n", + " 209r 1.2253738e+05 1.27e+02 1.74e+01 -3.2 1.09e+01 - 9.28e-01 8.33e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 1.2342956e+05 2.40e+03 2.42e+02 -3.2 1.70e+04 - 4.06e-01 1.26e-01f 1\n", + " 211r 1.2343158e+05 2.40e+03 7.66e+02 -3.2 8.82e+03 - 2.08e-01 1.77e-04h 1\n", + " 212r 1.2680154e+05 2.07e+03 8.71e+02 -3.2 2.55e+03 - 3.91e-01 1.86e-01h 1\n", + " 213r 1.2680301e+05 2.06e+03 1.05e+03 -3.2 9.06e+01 - 7.96e-01 5.94e-03h 1\n", + " 214r 1.2694462e+05 1.25e+03 8.56e+02 -3.2 7.71e+01 - 1.00e+00 3.94e-01h 1\n", + " 215r 1.2716494e+05 2.37e+03 2.47e+02 -3.2 4.31e+01 - 1.00e+00 1.00e+00h 1\n", + " 216r 1.2716480e+05 3.75e+02 2.05e+02 -3.2 1.32e+00 - 8.45e-01 9.35e-01h 1\n", + " 217r 1.2716432e+05 2.49e+01 7.82e+01 -3.2 2.34e-01 - 1.00e+00 9.40e-01h 1\n", + " 218r 1.2716443e+05 1.57e+00 2.02e+00 -3.2 1.03e-01 - 1.00e+00 1.00e+00h 1\n", + " 219r 1.2716444e+05 1.72e-01 1.84e-02 -3.2 3.20e-02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 220 1.2716441e+05 1.72e-01 5.84e+02 -1.0 3.35e+04 - 1.89e-04 1.11e-06f 3\n", + " 221 1.2716433e+05 1.72e-01 6.98e+03 -1.0 3.33e+04 - 5.76e-04 3.00e-06f 2\n", + " 222 1.2716001e+05 6.59e-01 6.09e+03 -1.0 3.26e+04 - 1.20e-04 1.53e-04f 1\n", + " 223 1.2715671e+05 9.98e-01 2.65e+04 -1.0 3.24e+04 - 8.81e-04 1.13e-04f 2\n", + " 224 1.2715642e+05 1.00e+00 3.99e+04 -1.0 3.21e+04 - 5.12e-04 1.02e-05f 8\n", + " 225 1.2715609e+05 1.00e+00 2.11e+05 -1.0 3.20e+04 - 6.44e-03 1.21e-05f 8\n", + " 226 1.2715594e+05 1.01e+00 2.22e+05 -1.0 3.12e+04 - 4.13e-04 7.29e-06f 9\n", + " 227 1.2715578e+05 1.01e+00 6.06e+05 -1.0 3.12e+04 - 1.45e-02 7.28e-06f 9\n", + " 228 1.2712455e+05 5.74e+01 5.61e+05 -1.0 2.98e+04 - 4.34e-04 2.11e-03f 1\n", + " 229 1.2712496e+05 5.76e+01 5.61e+05 -1.0 2.47e+04 - 1.73e-04 1.73e-04s 10\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 230 1.2713698e+05 1.14e+02 5.59e+05 -1.0 2.41e+04 - 2.70e-03 2.70e-03s 10\n", + " 231r 1.2713698e+05 1.14e+02 1.00e+03 2.1 0.00e+00 - 0.00e+00 0.00e+00R 1\n", + " 232r 1.2716197e+05 1.69e+03 3.15e+04 2.1 1.14e+05 - 1.07e-05 2.61e-04f 1\n", + " 233r 1.2714570e+05 2.14e+03 2.94e+04 2.1 8.31e+04 - 5.38e-04 1.00e-03f 1\n", + " 234r 1.2714342e+05 2.61e+03 2.90e+04 2.1 1.04e+04 - 2.06e-03 1.77e-03f 1\n", + " 235r 1.2713596e+05 3.50e+03 2.84e+04 2.1 1.57e+03 - 3.35e-03 4.25e-03f 1\n", + " 236r 1.2708154e+05 5.65e+03 2.84e+04 2.1 7.55e+02 - 2.00e-03 1.09e-02f 1\n", + " 237r 1.2708154e+05 5.08e+03 2.48e+04 2.1 8.00e+00 2.0 2.43e-02 1.02e-01f 1\n", + " 238r 1.2708154e+05 4.85e+03 2.33e+04 2.1 8.06e+00 1.5 3.31e-01 4.61e-02f 1\n", + " 239r 1.2708156e+05 1.14e+04 2.24e+04 2.1 2.91e+02 1.0 8.89e-03 1.92e-02f 2\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 240r 1.2708156e+05 3.64e+03 1.67e+03 2.1 3.56e-01 3.3 9.90e-01 9.24e-01f 1\n", + " 241r 1.2726934e+05 1.67e+04 1.27e+04 2.1 2.58e+02 - 4.63e-01 1.00e+00f 1\n", + " 242r 1.2736337e+05 1.24e+03 6.79e+01 2.1 2.54e+01 - 1.00e+00 1.00e+00f 1\n", + " 243r 1.2744147e+05 1.56e+03 1.20e+02 2.1 8.73e+01 - 1.00e+00 1.00e+00f 1\n", + " 244r 1.2739248e+05 1.69e+04 1.76e+02 2.1 4.12e+01 - 1.00e+00 1.00e+00f 1\n", + " 245r 1.2738697e+05 6.55e+02 5.20e+00 2.1 6.39e+00 - 1.00e+00 1.00e+00h 1\n", + " 246r 1.2749175e+05 1.38e+04 1.09e+03 1.4 1.60e+02 - 4.91e-01 7.12e-01f 1\n", + " 247r 1.2761275e+05 2.71e+03 4.74e+02 1.4 6.53e+01 - 6.43e-01 1.00e+00f 1\n", + " 248r 1.2750105e+05 1.80e+03 4.59e+01 1.4 3.96e+01 - 1.00e+00 1.00e+00f 1\n", + " 249r 1.2754311e+05 6.91e+01 1.63e+01 1.4 1.22e+01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 250r 1.2731384e+05 3.27e+03 7.52e+01 0.7 9.90e+01 - 9.32e-01 9.07e-01f 1\n", + " 251r 1.2733916e+05 3.31e+03 3.81e+02 0.7 2.94e+01 - 9.88e-01 1.00e+00f 1\n", + " 252r 1.2733916e+05 7.28e+00 2.53e+01 0.7 3.71e-02 2.8 1.00e+00 1.00e+00h 1\n", + " 253 1.2683674e+05 7.41e+03 1.23e+04 -1.0 3.89e+05 - 1.95e-04 3.22e-04f 1\n", + " 254 1.2676691e+05 7.46e+03 1.24e+04 -1.0 3.46e+05 - 8.15e-04 8.67e-05f 1\n", + " 255 1.2676634e+05 7.46e+03 1.25e+04 -1.0 3.35e+05 - 4.00e-06 1.86e-05f 1\n", + " 256r 1.2676634e+05 7.46e+03 9.99e+02 3.9 0.00e+00 - 0.00e+00 2.79e-07R 11\n", + " 257r 1.2676664e+05 6.95e+03 1.73e+03 3.9 7.46e+06 - 9.44e-06 6.75e-05f 1\n", + " 258r 1.2676749e+05 1.45e+04 4.19e+03 3.9 6.89e+06 - 5.87e-03 2.42e-04f 1\n", + " 259r 1.2677021e+05 2.06e+04 1.68e+05 3.9 7.68e+05 - 2.42e-01 6.81e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 260r 1.2676657e+05 1.54e+04 1.99e+04 3.2 2.06e+03 - 7.98e-01 2.46e-01f 1\n", + " 261r 1.2679614e+05 1.25e+05 6.11e+04 3.2 4.23e+02 - 6.64e-01 9.18e-01f 1\n", + " 262r 1.2679614e+05 1.06e+05 5.24e+04 3.2 2.15e+01 2.0 2.47e-01 1.50e-01h 1\n", + " 263r 1.2679699e+05 9.96e+04 4.99e+04 3.2 3.45e+02 - 1.19e-01 5.68e-02f 1\n", + " 264r 1.2667363e+05 3.90e+04 1.72e+04 3.2 9.75e+01 - 1.00e+00 9.82e-01f 1\n", + " 265r 1.2671998e+05 8.46e+04 5.46e+03 3.2 4.82e+01 - 9.57e-01 1.00e+00f 1\n", + " 266r 1.2672645e+05 3.56e+04 8.81e+03 3.2 3.41e+01 - 7.54e-01 5.00e-01f 2\n", + " 267r 1.2673515e+05 2.88e+04 2.96e+03 3.2 3.52e+01 - 8.41e-01 5.00e-01h 2\n", + " 268r 1.2674045e+05 2.96e+04 5.20e+02 3.2 1.42e+01 - 1.00e+00 1.00e+00h 1\n", + " 269r 1.2670264e+05 4.00e+04 1.89e+03 3.2 4.20e+01 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 270r 1.2671520e+05 2.66e+04 2.95e+03 3.2 3.23e+01 - 1.00e+00 5.00e-01h 2\n", + " 271r 1.2674449e+05 1.92e+04 6.30e+02 3.2 3.26e+01 - 1.00e+00 1.00e+00h 1\n", + " 272r 1.2667937e+05 1.21e+04 1.31e+03 3.2 4.68e+01 - 8.60e-01 8.81e-01H 1\n", + " 273r 1.2675843e+05 1.14e+05 1.38e+03 2.5 2.14e+02 - 9.15e-01 9.58e-01f 1\n", + " 274r 1.2689727e+05 2.02e+04 6.57e+02 2.5 1.53e+02 - 8.86e-01 9.29e-01f 1\n", + " 275r 1.2682834e+05 4.79e+03 1.01e+03 2.5 8.87e+01 - 1.29e-01 1.00e+00f 1\n", + " 276r 1.2683302e+05 7.29e+03 2.75e+01 2.5 1.48e+01 - 1.00e+00 1.00e+00f 1\n", + " 277r 1.2683771e+05 1.69e+02 2.08e+00 2.5 2.17e+00 - 1.00e+00 1.00e+00h 1\n", + " 278 9.8178178e+04 4.74e+03 3.17e+02 -1.0 1.14e+06 - 4.18e-03 3.73e-03f 1\n", + " 279 9.7892691e+04 4.74e+03 4.16e+02 -1.0 3.14e+05 - 1.05e-02 8.44e-05f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 280 9.7891957e+04 4.74e+03 6.56e+06 -1.0 9.57e+04 - 1.40e-02 8.51e-07f 1\n", + " 281 9.7890561e+04 4.74e+03 1.74e+11 -1.0 2.12e+07 - 2.28e-04 8.51e-09f 1\n", + " 282 8.8769650e+04 4.74e+03 7.10e+11 -1.0 7.63e+07 - 7.92e-05 1.93e-05f 1\n", + " 283r 8.8769650e+04 4.74e+03 1.00e+03 3.7 0.00e+00 - 0.00e+00 7.21e-12R 2\n", + " 284r 8.8769664e+04 3.34e+03 2.82e+04 3.7 4.74e+06 - 5.33e-02 2.94e-04f 1\n", + " 285 8.8693654e+04 3.34e+03 3.82e+02 -1.0 1.57e+05 - 1.43e-04 4.15e-05f 1\n", + " 286 8.8692951e+04 3.34e+03 2.28e+03 -1.0 1.43e+05 - 2.18e-04 4.17e-07f 1\n", + " 287r 8.8692951e+04 3.34e+03 9.99e+02 3.5 0.00e+00 - 0.00e+00 2.08e-09R 2\n", + " 288r 8.8692949e+04 3.30e+03 4.79e+03 3.5 3.34e+06 - 1.41e-03 1.30e-05f 1\n", + " 289r 8.8693153e+04 5.46e+02 4.17e+04 3.5 1.37e+06 - 1.36e-01 2.38e-03f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 290 8.7457681e+04 5.52e+02 9.15e+02 -1.0 3.59e+05 - 1.38e-02 3.41e-04f 1\n", + " 291 8.7456415e+04 5.52e+02 4.84e+06 -1.0 5.31e+04 - 1.82e-02 3.49e-06f 1\n", + " 292r 8.7456415e+04 5.52e+02 1.00e+03 2.7 0.00e+00 - 0.00e+00 1.76e-08R 2\n", + " 293r 8.7456389e+04 1.39e+02 2.42e+04 2.7 5.52e+05 - 4.97e-01 9.90e-04f 1\n", + " 294 8.7370462e+04 1.39e+02 5.88e+02 -1.0 3.62e+05 - 1.40e-02 2.36e-05f 1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 295r 8.7370462e+04 1.39e+02 9.99e+02 2.1 0.00e+00 - 0.00e+00 1.18e-07R 2\n", + " 296r 8.7370048e+04 3.52e+01 3.53e+03 2.1 1.39e+05 - 2.88e-01 9.90e-04f 1\n", + " 297 8.7365867e+04 3.52e+01 8.57e+03 -1.0 5.17e+04 - 1.49e-02 1.02e-05f 1\n", + " 298r 8.7365867e+04 3.52e+01 1.00e+03 1.5 0.00e+00 - 0.00e+00 5.08e-08R 2\n", + " 299r 8.7366392e+04 9.28e+00 9.94e+02 1.5 3.52e+04 - 2.03e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 300 8.7366287e+04 9.28e+00 8.33e+05 -1.0 7.00e+04 - 1.52e-02 7.75e-07f 2\n", + " 301r 8.7366287e+04 9.28e+00 1.00e+03 1.0 0.00e+00 - 0.00e+00 3.92e-07R 2\n", + " 302r 8.7367439e+04 1.24e+01 1.01e+03 1.0 9.28e+03 - 3.08e-02 9.90e-04f 1\n", + " 303r 8.7397075e+04 3.59e+03 9.77e+02 1.0 3.75e+02 - 1.00e-01 2.88e-02f 1\n", + " 304r 8.7438378e+04 3.48e+03 9.08e+02 1.0 3.31e+02 - 8.91e-02 4.71e-02f 1\n", + " 305r 8.7508053e+04 5.97e+03 1.50e+03 1.0 2.88e+02 - 4.19e-01 8.34e-02f 1\n", + " 306r 8.7712845e+04 2.48e+04 3.57e+03 1.0 2.81e+02 - 8.23e-01 3.25e-01f 1\n", + " 307r 8.7793008e+04 1.34e+04 2.30e+03 1.0 5.17e+01 - 4.78e-01 4.32e-01f 1\n", + " 308r 8.7846425e+04 7.72e+03 1.02e+03 1.0 2.62e+01 - 7.14e-01 6.69e-01f 1\n", + " 309r 8.7909231e+04 2.83e+03 4.55e+03 1.0 2.21e+01 - 9.91e-01 6.64e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 310r 8.7935450e+04 1.38e+03 2.75e+03 1.0 1.16e+01 - 6.88e-01 5.11e-01f 1\n", + " 311r 8.7934743e+04 7.89e+01 4.04e+02 1.0 5.65e+00 - 1.00e+00 1.00e+00f 1\n", + " 312r 8.7774627e+04 2.97e+03 1.68e+02 0.3 4.16e+01 - 9.23e-01 9.88e-01f 1\n", + " 313r 8.8807837e+04 4.00e+03 1.24e+01 0.3 1.93e+02 - 1.00e+00 1.00e+00h 1\n", + " 314r 8.8874130e+04 2.92e+02 1.89e+00 0.3 9.71e+00 - 1.00e+00 1.00e+00h 1\n", + " 315r 8.8879501e+04 1.07e+00 1.78e-02 0.3 1.06e+00 - 1.00e+00 1.00e+00h 1\n", + " 316r 8.8879501e+04 1.07e+00 9.99e+02 0.0 0.00e+00 - 0.00e+00 2.69e-07R 2\n", + " 317r 8.8881473e+04 2.72e-01 1.76e+04 0.0 1.07e+03 - 9.21e-01 9.90e-04f 1\n", + " 318r 8.8881473e+04 2.72e-01 9.99e+02 -0.6 0.00e+00 - 0.00e+00 2.66e-07R 2\n", + " 319r 8.8884807e+04 2.82e-01 1.14e+03 -0.6 7.03e+02 - 2.34e-01 9.90e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 320r 8.9636313e+04 9.61e+02 5.59e+03 -0.6 8.27e+02 - 8.63e-01 1.73e-01f 1\n", + " 321r 9.0993769e+04 1.08e+03 5.48e+03 -0.6 7.71e+02 - 5.54e-01 3.35e-01f 1\n", + " 322r 9.2474307e+04 2.15e+03 5.68e+03 -0.6 4.81e+02 - 8.60e-01 5.30e-01f 1\n", + " 323r 9.3478773e+04 1.06e+03 1.62e+03 -0.6 1.77e+02 - 9.90e-01 8.80e-01h 1\n", + " 324r 9.3554925e+04 1.01e+02 2.92e+01 -0.6 1.84e+01 - 9.96e-01 1.00e+00h 1\n", + " 325r 9.3556224e+04 1.65e-01 1.08e-02 -0.6 2.08e-01 - 1.00e+00 1.00e+00h 1\n", + " 326r 9.3556224e+04 1.65e-01 9.99e+02 -0.8 0.00e+00 - 0.00e+00 2.98e-10R 2\n", + " 327r 9.3571208e+04 1.65e-01 1.76e+04 -0.8 9.65e+02 - 8.70e-01 2.51e-03f 1\n", + " 328r 9.8897161e+04 1.50e+03 3.13e+03 -0.8 1.01e+03 - 9.59e-01 8.71e-01f 1\n", + " 329r 9.8336345e+04 5.99e+01 1.09e+02 -0.8 7.97e+01 - 9.90e-01 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 330r 9.8338262e+04 4.49e-01 4.27e-01 -0.8 3.37e+00 - 9.95e-01 1.00e+00h 1\n", + " 331r 9.8363923e+04 2.98e+02 1.32e+02 -1.5 9.78e+00 - 1.00e+00 9.63e-01f 1\n", + " 332r 1.0078662e+05 2.43e+02 1.46e+02 -1.5 6.27e+02 - 1.00e+00 6.63e-01h 1\n", + " 333r 1.0169690e+05 9.17e+01 9.25e+01 -1.5 1.53e+02 - 1.00e+00 7.05e-01h 1\n", + " 334r 1.0207081e+05 2.83e+00 2.90e+00 -1.5 3.21e+01 - 1.00e+00 1.00e+00h 1\n", + " 335r 1.0207272e+05 1.92e-01 6.60e-02 -1.5 8.17e+00 - 1.00e+00 1.00e+00h 1\n", + " 336r 1.0210277e+05 2.14e+02 1.11e+02 -2.2 5.08e+00 - 1.00e+00 9.77e-01f 1\n", + " 337r 1.0356247e+05 1.01e+03 5.29e+02 -2.2 5.28e+02 - 4.61e-01 2.44e-01h 1\n", + " 338r 1.0508487e+05 2.49e+03 4.03e+03 -2.2 3.97e+02 - 1.00e+00 3.31e-01h 1\n", + " 339r 1.0815887e+05 1.05e+03 6.46e+02 -2.2 2.67e+02 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 340r 1.0790832e+05 9.75e+01 1.58e+01 -2.2 2.29e+01 - 1.00e+00 1.00e+00h 1\n", + " 341r 1.0799170e+05 2.00e+01 1.12e+00 -2.2 7.74e+00 - 1.00e+00 1.00e+00h 1\n", + " 342r 1.0799969e+05 1.96e-01 1.83e-02 -2.2 7.42e-01 - 1.00e+00 1.00e+00h 1\n", + " 343r 1.0799977e+05 1.96e-01 1.39e-06 -2.2 6.97e-03 - 1.00e+00 1.00e+00h 1\n", + " 344r 1.0810014e+05 1.22e+00 2.91e+02 -5.0 2.10e+01 - 8.95e-01 4.72e-01f 1\n", + " 345r 1.0810406e+05 4.81e+00 2.50e+02 -5.0 8.05e-01 -2.0 3.48e-01 4.35e-01h 1\n", + " 346r 1.0823331e+05 4.73e+00 3.13e+02 -5.0 6.45e+03 - 2.53e-01 1.89e-02f 1\n", + " 347r 1.0723140e+05 1.69e+02 4.34e+02 -5.0 1.58e+03 - 3.99e-03 4.40e-01h 1\n", + " 348r 1.0742343e+05 1.63e+02 3.79e+02 -5.0 1.51e+03 - 6.57e-01 6.72e-02h 1\n", + " 349r 1.0834320e+05 2.55e+02 5.98e+02 -5.0 1.45e+03 - 1.56e-01 3.47e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 350r 1.0905675e+05 4.18e+02 9.23e+02 -5.0 1.03e+03 - 2.62e-02 7.65e-01h 1\n", + " 351r 1.1388747e+05 2.64e+03 2.51e+03 -5.0 1.45e+03 - 2.53e-01 6.38e-01h 1\n", + " 352r 1.1388763e+05 1.74e+03 4.40e+03 -5.0 7.03e-01 -2.5 8.02e-01 3.41e-01h 1\n", + " 353r 1.1388766e+05 1.73e+03 6.62e+03 -5.0 5.05e-01 -3.0 9.72e-01 9.80e-03h 1\n", + " 354r 1.1417543e+05 1.41e+03 5.38e+03 -5.0 7.36e+02 - 4.04e-02 1.84e-01h 1\n", + " 355r 1.1417550e+05 1.40e+03 5.61e+03 -5.0 1.38e+00 -3.4 1.00e+00 3.66e-03h 1\n", + " 356r 1.1550772e+05 4.07e+02 1.18e+03 -5.0 7.26e+02 - 4.25e-02 8.35e-01h 1\n", + " 357r 1.1552641e+05 2.23e+02 7.45e+02 -5.0 4.56e+00 -3.9 6.30e-01 4.52e-01h 1\n", + " 358r 1.1558163e+05 1.25e+02 4.23e+02 -5.0 1.37e+01 -4.4 9.96e-02 4.40e-01h 1\n", + " 359r 1.1577336e+05 1.09e+02 5.76e+02 -5.0 4.44e+01 -4.9 7.36e-02 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 360r 1.1577561e+05 2.45e+03 5.78e+02 -5.0 7.08e+00 -2.6 1.51e-01 1.00e+00h 1\n", + " 361r 1.1577726e+05 1.89e+03 2.65e+02 -5.0 4.00e+00 -3.1 7.58e-01 2.50e-01h 3\n", + " 362r 1.1578214e+05 1.53e+03 1.98e+02 -5.0 5.80e+00 -3.6 3.32e-01 2.50e-01h 3\n", + " 363r 1.1578330e+05 1.50e+03 1.65e+02 -5.0 8.12e+00 -4.1 1.00e+00 2.01e-02h 6\n", + " 364r 1.1578639e+05 1.48e+03 1.42e+02 -5.0 1.72e+01 -4.5 4.68e-01 1.80e-02h 6\n", + " 365r 1.1592763e+05 1.40e+03 1.17e+02 -5.0 5.18e+01 -5.0 5.33e-01 2.75e-01h 2\n", + " 366r 1.1617094e+05 1.53e+03 9.71e+01 -5.0 1.50e+02 -5.5 1.75e-01 1.67e-01h 1\n", + " 367r 1.1703261e+05 1.26e+03 8.04e+01 -5.0 5.54e+02 -6.0 3.66e-01 1.80e-01h 1\n", + " 368r 1.2972938e+05 4.18e+03 1.66e+02 -5.0 2.79e+03 -6.4 2.07e-01 7.16e-01h 1\n", + " 369r 1.2972954e+05 4.18e+03 3.20e+02 -5.0 8.11e+02 -6.0 3.98e-01 3.44e-05h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 370r 1.2975480e+05 4.04e+03 5.38e+02 -5.0 1.31e+02 -3.8 1.19e-02 3.23e-02h 1\n", + " 371r 1.2964740e+05 3.38e+03 4.90e+02 -5.0 1.09e+02 -4.3 1.67e-03 1.64e-01h 1\n", + " 372r 1.2966158e+05 2.40e+03 3.46e+02 -5.0 7.46e+00 -3.8 2.68e-01 2.91e-01h 1\n", + " 373r 1.2973030e+05 1.27e+03 1.84e+02 -5.0 2.25e+01 -4.3 1.00e+00 4.68e-01h 1\n", + " 374r 1.3017019e+05 5.33e+01 4.05e+02 -5.0 6.82e+01 -4.8 3.63e-01 1.00e+00h 1\n", + " 375r 1.3028200e+05 5.05e+01 3.67e+02 -5.0 2.24e+02 -5.3 1.06e-01 7.97e-02h 1\n", + " 376r 1.3069758e+05 4.92e+01 3.93e+02 -5.0 8.09e+02 -5.7 4.51e-02 7.81e-02h 1\n", + " 377r 1.3069758e+05 4.92e+01 3.90e+02 -5.0 2.98e+03 - 1.65e-02 3.13e-05h 7\n", + " 378r 1.3069919e+05 4.92e+01 4.31e+02 -5.0 1.68e+03 - 1.08e-01 3.30e-04h 5\n", + " 379r 1.3126228e+05 4.78e+01 4.36e+02 -5.0 9.27e+02 - 1.70e-01 7.48e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 380r 1.3306851e+05 3.73e+01 4.13e+02 -5.0 9.00e+02 - 4.51e-01 2.48e-01h 1\n", + " 381r 1.3831309e+05 1.63e+02 4.11e+02 -5.0 6.80e+02 - 1.96e-01 9.55e-01h 1\n", + " 382r 1.3831686e+05 1.59e+02 4.88e+02 -5.0 2.62e+01 - 1.36e-02 2.42e-02h 1\n", + " 383r 1.3854324e+05 2.37e+01 6.34e+02 -5.0 2.99e+01 - 3.17e-01 9.37e-01H 1\n", + " 384r 1.3854435e+05 2.30e+01 5.98e+02 -5.0 1.92e+01 - 3.14e-02 6.34e-02h 1\n", + " 385r 1.3855788e+05 1.90e+02 3.37e+02 -5.0 1.61e+01 - 6.68e-01 1.00e+00h 1\n", + " 386r 1.3855814e+05 3.75e+00 1.12e+01 -5.0 9.39e-02 - 9.55e-01 1.00e+00h 1\n", + " 387r 1.3855815e+05 4.13e+00 6.63e+02 -5.0 1.20e+00 - 3.35e-01 1.68e-01H 1\n", + " 388r 1.3855831e+05 1.34e+02 1.92e+01 -5.0 8.03e-01 - 1.00e+00 1.00e+00h 1\n", + " 389r 1.3855837e+05 9.15e+00 1.46e+00 -5.0 1.61e-01 - 1.00e+00 1.00e+00h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 390r 1.3855836e+05 2.45e-01 1.28e+00 -5.0 2.43e-02 - 1.00e+00 1.00e+00h 1\n", + " 391r 1.3855836e+05 2.45e-01 3.53e-02 -5.0 1.11e-03 - 1.00e+00 1.00e+00h 1\n", + " 392r 1.3855836e+05 2.45e-01 1.21e-06 -5.0 2.41e-05 - 1.00e+00 1.00e+00h 1\n", + " 393r 1.3855744e+05 2.08e+01 5.23e+02 -7.5 5.05e-01 - 8.64e-01 7.40e-01f 1\n", + " 394r 1.3855744e+05 1.51e+01 9.25e+02 -7.5 1.29e+00 - 2.87e-01 3.84e-01h 1\n", + " 395r 1.3855750e+05 8.64e+00 8.72e+02 -7.5 6.46e-01 - 4.26e-01 4.61e-01h 1\n", + " 396r 1.3855752e+05 4.84e+00 4.49e+02 -7.5 3.22e-01 - 6.28e-01 6.53e-01h 1\n", + " 397r 1.3855749e+05 3.20e+00 4.97e+02 -7.5 1.50e-01 - 2.97e-01 4.40e-01h 1\n", + " 398r 1.3855747e+05 1.96e+00 6.90e+02 -7.5 3.00e-02 -2.6 4.68e-02 3.88e-01h 1\n", + " 399r 1.3855745e+05 5.42e-01 5.37e+02 -7.5 2.62e-02 -3.1 3.97e-01 7.24e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 400r 1.3855744e+05 4.46e-01 3.86e+02 -7.5 2.77e-02 -2.7 2.69e-01 1.80e-01h 1\n", + " 401r 1.3855744e+05 4.34e-01 5.63e+02 -7.5 1.66e-01 -3.1 2.98e-01 2.76e-02h 1\n", + " 402r 1.3855738e+05 4.70e+00 6.16e+02 -7.5 6.32e-01 - 1.00e+00 2.87e-01h 1\n", + " 403r 1.3855735e+05 5.14e+00 3.38e+02 -7.5 3.82e-01 - 1.00e+00 2.07e-01h 1\n", + " 404r 1.3855722e+05 1.35e+01 1.78e+00 -7.5 2.46e-01 - 1.00e+00 1.00e+00h 1\n", + " 405r 1.3855722e+05 2.45e-01 1.38e-02 -7.5 1.58e-02 - 1.00e+00 1.00e+00h 1\n", + " 406r 1.3855722e+05 2.45e-01 2.29e-04 -7.5 3.59e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 406\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 1.3855721777671148e+05 1.3855721777671148e+05\n", + "Dual infeasibility......: 6.9379110321402369e+00 6.9379110321402369e+00\n", + "Constraint violation....: 2.4525985132130276e-01 2.4525985132130276e-01\n", + "Complementarity.........: 3.1231128787715433e-08 3.1231128787715433e-08\n", + "Overall NLP error.......: 6.9379110321402369e+00 6.9379110321402369e+00\n", + "\n", + "\n", + "Number of objective function evaluations = 723\n", + "Number of objective gradient evaluations = 182\n", + "Number of equality constraint evaluations = 723\n", + "Number of inequality constraint evaluations = 723\n", + "Number of equality constraint Jacobian evaluations = 446\n", + "Number of inequality constraint Jacobian evaluations = 446\n", + "Number of Lagrangian Hessian evaluations = 407\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.635\n", + "Total CPU secs in NLP function evaluations = 0.068\n", + "\n", + "EXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n" + ] + } + ], + "source": [ + "results = solver.solve(m, tee=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 138557.21777671148\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -0.0040595 : watt : False : (None, None)\n", + " Pressure Change : -2.4174e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 4.8078e-08 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 0.91034 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.089660 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.95213 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.041932 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.0029849 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.0029553 - - \n", + " Temperature kelvin 432.09 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 8.7385e-09 \n", + " flow_mol_phase Vap mole / second - 1.0000e-12 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.67175 0.67175 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.32825 0.32825 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.47214 0.47214 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.085798 0.085798 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.22083 0.22083 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.22124 0.22124 \n", + " temperature kelvin - 344.53 344.53 \n", + " pressure pascal - 1.0826e+05 1.0826e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8462216452944548\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -36576. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate Liq mole / second 0.17702 - - \n", + " Total Molar Flowrate Vap mole / second 0.068244 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 1.1730e-07 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 2.4279e-07 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 1.0000 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 1.0000e-20 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 1.0000e-20 - - \n", + " Temperature kelvin 800.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 4.8078e-08 \n", + " flow_mol_phase Vap mole / second - 1.0000e-12 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.91034 0.91034 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.089660 0.089660 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.95213 0.95213 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.041932 0.041932 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.0029849 0.0029849 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.0029553 0.0029553 \n", + " temperature kelvin - 432.09 432.09 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 800.000 K\n", + "\n", + "F101 outlet temperature = 432.088 K\n", + "\n", + "F102 outlet temperature = 344.531 K\n", + "F102 outlet pressure = 108260.028 Pa\n", + "\n" + ] + } + ], + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb index 6040564f..e8169a6a 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_exercise.ipynb @@ -1,2505 +1,2980 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb index 56db9c65..5f2b6695 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_solution.ipynb @@ -1,2869 +1,3243 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb index 6369d0f7..471da278 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_test.ipynb @@ -1,2713 +1,3122 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.810084Z", - "start_time": "2025-06-26T20:17:04.786754Z" - } - }, - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 29" - ], - "outputs": [], - "execution_count": 29 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.104838Z", - "start_time": "2025-06-26T20:17:05.080097Z" - } - }, - "source": [ - "# Check the degrees of freedom\n", - "assert degrees_of_freedom(m) == 0" - ], - "outputs": [], - "execution_count": 40 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.713878Z", - "start_time": "2025-06-26T20:17:07.711084Z" - } - }, - "source": [ - "# Check solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ], - "outputs": [], - "execution_count": 57 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.014719Z", - "start_time": "2025-06-26T20:17:07.926032Z" - } - }, - "source": [ - "import pytest\n", - "\n", - "assert value(m.fs.operating_cost) == pytest.approx(419122.3387, abs=1e-3)" - ], - "outputs": [], - "execution_count": 61 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.063578Z", - "start_time": "2025-06-26T20:17:08.060157Z" - } - }, - "source": [ - "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7352.4828, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" - ], - "outputs": [], - "execution_count": 63 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.275146Z", - "start_time": "2025-06-26T20:17:08.249526Z" - } - }, - "source": [ - "assert degrees_of_freedom(m) == 5" - ], - "outputs": [], - "execution_count": 69 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.683743Z", - "start_time": "2025-06-26T20:17:08.679403Z" - } - }, - "source": [ - "# Check for solver solve status\n", - "from pyomo.environ import TerminationCondition\n", - "\n", - "assert results.solver.termination_condition == TerminationCondition.optimal" - ], - "outputs": [], - "execution_count": 79 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.756874Z", - "start_time": "2025-06-26T20:17:08.753678Z" - } - }, - "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(312786.338, abs=1e-3)\n", - "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" - ], - "outputs": [], - "execution_count": 81 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "testing" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.825473Z", - "start_time": "2025-06-26T20:17:08.820372Z" - } - }, - "source": [ - "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3)\n", - "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.878, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", - "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" - ], - "outputs": [], - "execution_count": 83 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.409008Z", + "start_time": "2025-11-20T21:46:10.382157Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 29" + ], + "outputs": [], + "execution_count": 28 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.568992Z", + "start_time": "2025-11-20T21:46:10.542995Z" + } + }, + "source": [ + "# Check the degrees of freedom\n", + "assert degrees_of_freedom(m) == 0" + ], + "outputs": [], + "execution_count": 39 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.393870Z", + "start_time": "2025-11-20T21:46:17.390132Z" + } + }, + "source": [ + "# Check solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 56 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.571498Z", + "start_time": "2025-11-20T21:46:17.493194Z" + } + }, + "source": [ + "import pytest\n", + "\n", + "assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3)" + ], + "outputs": [], + "execution_count": 60 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.619054Z", + "start_time": "2025-11-20T21:46:17.613393Z" + } + }, + "source": [ + "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" + ], + "outputs": [], + "execution_count": 62 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.759351Z", + "start_time": "2025-11-20T21:46:17.728327Z" + } + }, + "source": [ + "assert degrees_of_freedom(m) == 5" + ], + "outputs": [], + "execution_count": 68 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.045752Z", + "start_time": "2025-11-20T21:46:18.041549Z" + } + }, + "source": [ + "# Check for solver solve status\n", + "from pyomo.environ import TerminationCondition\n", + "\n", + "assert results.solver.termination_condition == TerminationCondition.optimal" + ], + "outputs": [], + "execution_count": 78 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.093619Z", + "start_time": "2025-11-20T21:46:18.090039Z" + } + }, + "source": [ + "assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3)\n", + "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" + ], + "outputs": [], + "execution_count": 80 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "testing" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:19.262061Z", + "start_time": "2025-11-20T21:46:18.121920Z" + } + }, + "source": [ + "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", + "print(value(m.fs.R101.outlet.temperature[0]))\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3)\n", + "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", + "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "763.5072359720118\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAssertionError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[82]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.H101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m500\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m763.484\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F101.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m301.881\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 5\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F102.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m362.935\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n", + "\u001b[31mAssertionError\u001b[39m: " + ] + } + ], + "execution_count": 82 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb index 56db9c65..5f2b6695 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet_usr.ipynb @@ -1,2869 +1,3243 @@ { - "cells": [ - { - "cell_type": "code", - "metadata": { - "tags": [ - "header", - "hide-cell" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.034501Z", - "start_time": "2025-06-26T20:17:01.030269Z" - } - }, - "source": [ - "###############################################################################\n", - "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", - "# Framework (idaes IP) was produced under the DOE Institute for the\n", - "# Design of Advanced Energy Systems (IDAES).\n", - "#\n", - "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", - "# University of California, through Lawrence Berkeley National Laboratory,\n", - "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", - "# University, West Virginia University Research Corporation, et al.\n", - "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", - "# for full copyright and license information.\n", - "###############################################################################" - ], - "outputs": [], - "execution_count": 1 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# HDA Flowsheet Simulation and Optimization\n", - "\n", - "Author: Jaffer Ghouse
\n", - "Maintainer: Tanner Polley
\n", - "Updated: 2025-06-03\n", - "\n", - "## Learning outcomes\n", - "\n", - "\n", - "- Construct a steady-state flowsheet using the IDAES unit model library\n", - "- Connecting unit models in a flowsheet using Arcs\n", - "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", - "- Formulate and solve an optimization problem\n", - " - Defining an objective function\n", - " - Setting variable bounds\n", - " - Adding additional constraints\n", - "\n", - "\n", - "The general workflow of setting up an IDAES flowsheet is the following:\n", - "\n", - "     1 Importing Modules
\n", - "     2 Building a Model
\n", - "     3 Scaling the Model
\n", - "     4 Specifying the Model
\n", - "     5 Initializing the Model
\n", - "     6 Solving the Model
\n", - "     7 Analyzing and Visualizing the Results
\n", - "     8 Optimizing the Model
\n", - "\n", - "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", - "\n", - "\n", - "## Problem Statement\n", - "\n", - "Hydrodealkylation is a chemical reaction that often involves reacting\n", - "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", - "simpler aromatic hydrocarbon devoid of functional groups. In this\n", - "example, toluene will be reacted with hydrogen gas at high temperatures\n", - " to form benzene via the following reaction:\n", - "\n", - "**C6H5CH3 + H2 \u2192 C6H6 + CH4**\n", - "\n", - "\n", - "This reaction is often accompanied by an equilibrium side reaction\n", - "which forms diphenyl, which we will neglect for this example.\n", - "\n", - "This example is based on the 1967 AIChE Student Contest problem as\n", - "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", - "McGraw-Hill.\n", - "\n", - "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", - "\n", - "- hda_ideal_VLE.py\n", - "- hda_reaction.py\n", - "\n", - "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1 Importing Modules\n", - "### 1.1 Importing required Pyomo and IDAES components\n", - "\n", - "\n", - "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", - "- Constraint (to write constraints)\n", - "- Var (to declare variables)\n", - "- ConcreteModel (to create the concrete model object)\n", - "- Expression (to evaluate values as a function of variables defined in the model)\n", - "- Objective (to define an objective function for optimization)\n", - "- SolverFactory (to solve the problem)\n", - "- TransformationFactory (to apply certain transformations)\n", - "- Arc (to connect two unit models)\n", - "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", - "\n", - "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:01.631380Z", - "start_time": "2025-06-26T20:17:01.240873Z" - } - }, - "source": [ - "from pyomo.environ import (\n", - " Constraint,\n", - " Var,\n", - " ConcreteModel,\n", - " Expression,\n", - " Objective,\n", - " SolverFactory,\n", - " TransformationFactory,\n", - " value,\n", - ")\n", - "from pyomo.network import Arc, SequentialDecomposition" - ], - "outputs": [], - "execution_count": 2 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", - "- Feed\n", - "- Mixer\n", - "- Heater\n", - "- StoichiometricReactor\n", - "- **Flash**\n", - "- Separator (splitter) \n", - "- PressureChanger\n", - "- Product" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.331120Z", - "start_time": "2025-06-26T20:17:01.647431Z" - } - }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], - "outputs": [], - "execution_count": 3 - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.461993Z", - "start_time": "2025-06-26T20:17:03.340761Z" - } - }, - "source": [ - "from idaes.models.unit_models import (\n", - " PressureChanger,\n", - " IsentropicPressureChangerInitializer,\n", - " Mixer,\n", - " MixerInitializer,\n", - " Separator as Splitter,\n", - " SeparatorInitializer,\n", - " Heater,\n", - " StoichiometricReactor,\n", - " Feed,\n", - " Product,\n", - ")" - ], - "outputs": [], - "execution_count": 4 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.473539Z", - "start_time": "2025-06-26T20:17:03.471144Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models" - ], - "outputs": [], - "execution_count": 5 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.493114Z", - "start_time": "2025-06-26T20:17:03.490661Z" - } - }, - "source": [ - "# Todo: import flash model from idaes.models.unit_models\n", - "from idaes.models.unit_models import Flash" - ], - "outputs": [], - "execution_count": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.516199Z", - "start_time": "2025-06-26T20:17:03.512942Z" - } - }, - "source": [ - "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", - "from idaes.core.util.model_statistics import degrees_of_freedom\n", - "from idaes.core.scaling.util import set_scaling_factor\n", - "from idaes.core.scaling.autoscaling import AutoScaler\n", - "\n", - "# Import idaes logger to set output levels\n", - "import idaes.logger as idaeslog\n", - "from idaes.core.solvers import get_solver\n", - "from idaes.core.util.exceptions import InitializationError" - ], - "outputs": [], - "execution_count": 7 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1.2 Importing required thermo and reaction package\n", - "\n", - "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", - "\n", - "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", - "\n", - "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", - "
    \n", - "
  • hda_ideal_VLE as thermo_props
  • \n", - "
  • hda_reaction as reaction_props
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.551358Z", - "start_time": "2025-06-26T20:17:03.543942Z" - } - }, - "source": [ - "from idaes_examples.mod.hda import hda_ideal_VLE as thermo_props\n", - "from idaes_examples.mod.hda import hda_reaction as reaction_props" - ], - "outputs": [], - "execution_count": 8 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2 Constructing the Flowsheet\n", - "\n", - "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.572038Z", - "start_time": "2025-06-26T20:17:03.567506Z" - } - }, - "source": [ - "m = ConcreteModel()\n", - "m.fs = FlowsheetBlock(dynamic=False)" - ], - "outputs": [], - "execution_count": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.606045Z", - "start_time": "2025-06-26T20:17:03.591939Z" - } - }, - "source": [ - "m.fs.thermo_params = thermo_props.HDAParameterBlock()\n", - "m.fs.reaction_params = reaction_props.HDAReactionParameterBlock(\n", - " property_package=m.fs.thermo_params\n", - ")" - ], - "outputs": [], - "execution_count": 10 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.1 Adding Unit Models\n", - "\n", - "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.643943Z", - "start_time": "2025-06-26T20:17:03.617017Z" - } - }, - "source": [ - "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.M101 = Mixer(\n", - " property_package=m.fs.thermo_params,\n", - " num_inlets=3,\n", - ")\n", - "\n", - "m.fs.H101 = Heater(\n", - " property_package=m.fs.thermo_params,\n", - " has_pressure_change=False,\n", - " has_phase_equilibrium=True,\n", - ")" - ], - "outputs": [], - "execution_count": 11 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"reaction_package\": m.fs.reaction_params
  • \n", - "
  • \"has_heat_of_reaction\": True
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.659010Z", - "start_time": "2025-06-26T20:17:03.655218Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above" - ], - "outputs": [], - "execution_count": 12 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.684875Z", - "start_time": "2025-06-26T20:17:03.673453Z" - } - }, - "source": [ - "# Todo: Add reactor with the specifications above\n", - "m.fs.R101 = StoichiometricReactor(\n", - " property_package=m.fs.thermo_params,\n", - " reaction_package=m.fs.reaction_params,\n", - " has_heat_of_reaction=True,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=False,\n", - ")" - ], - "outputs": [], - "execution_count": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", - "
    \n", - "
  • \"property_package\": m.fs.thermo_params
  • \n", - "
  • \"has_heat_transfer\": True
  • \n", - "
  • \"has_pressure_change\": False
  • \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.716786Z", - "start_time": "2025-06-26T20:17:03.705239Z" - } - }, - "source": [ - "m.fs.F101 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.746908Z", - "start_time": "2025-06-26T20:17:03.723650Z" - } - }, - "source": [ - "m.fs.S101 = Splitter(\n", - " property_package=m.fs.thermo_params,\n", - " ideal_separation=False,\n", - " outlet_list=[\"purge\", \"recycle\"],\n", - ")\n", - "\n", - "\n", - "m.fs.C101 = PressureChanger(\n", - " property_package=m.fs.thermo_params,\n", - " compressor=True,\n", - " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", - ")\n", - "\n", - "m.fs.F102 = Flash(\n", - " property_package=m.fs.thermo_params,\n", - " has_heat_transfer=True,\n", - " has_pressure_change=True,\n", - ")" - ], - "outputs": [], - "execution_count": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.762882Z", - "start_time": "2025-06-26T20:17:03.753179Z" - } - }, - "source": [ - "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", - "m.fs.P103 = Product(property_package=m.fs.thermo_params)" - ], - "outputs": [], - "execution_count": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2 Connecting Unit Models using Arcs\n", - "\n", - "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](HDA_flowsheet.png)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.774984Z", - "start_time": "2025-06-26T20:17:03.771782Z" - } - }, - "source": [ - "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", - "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", - "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" - ], - "outputs": [], - "execution_count": 17 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.788343Z", - "start_time": "2025-06-26T20:17:03.786044Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet" - ], - "outputs": [], - "execution_count": 18 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.809066Z", - "start_time": "2025-06-26T20:17:03.806273Z" - } - }, - "source": [ - "# Todo: Connect the H101 outlet to R101 inlet\n", - "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" - ], - "outputs": [], - "execution_count": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.832036Z", - "start_time": "2025-06-26T20:17:03.827498Z" - } - }, - "source": [ - "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", - "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", - "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", - "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", - "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" - ], - "outputs": [], - "execution_count": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.870751Z", - "start_time": "2025-06-26T20:17:03.867184Z" - } - }, - "source": [ - "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", - "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", - "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" - ], - "outputs": [], - "execution_count": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.930448Z", - "start_time": "2025-06-26T20:17:03.908145Z" - } - }, - "source": [ - "TransformationFactory(\"network.expand_arcs\").apply_to(m)" - ], - "outputs": [], - "execution_count": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 Adding expressions to compute purity and operating costs\n", - "\n", - "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", - "\n", - "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.948996Z", - "start_time": "2025-06-26T20:17:03.945721Z" - } - }, - "source": [ - "m.fs.purity = Expression(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " / (\n", - " m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " + m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")" - ], - "outputs": [], - "execution_count": 23 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:03.977346Z", - "start_time": "2025-06-26T20:17:03.974044Z" - } - }, - "source": [ - "m.fs.cooling_cost = Expression(\n", - " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", - ")" - ], - "outputs": [], - "execution_count": 24 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", - "
    \n", - "
  • 2.2E-4 dollars/kW for H101
  • \n", - "
  • 1.9E-4 dollars/kW for F102
  • \n", - "
\n", - "Note that the heat duty is in units of watt (J/s). " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.000678Z", - "start_time": "2025-06-26T20:17:03.998071Z" - } - }, - "source": [ - "m.fs.heating_cost = Expression(\n", - " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", - ")" - ], - "outputs": [], - "execution_count": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.039083Z", - "start_time": "2025-06-26T20:17:04.036119Z" - } - }, - "source": [ - "m.fs.operating_cost = Expression(\n", - " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", - ")" - ], - "outputs": [], - "execution_count": 26 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3 Scaling the Model\n", - "\n", - "In this example, we will simply use the ``AutoScaler`` method to scale our model since this example is focused on introductory flowsheet building for a full process system.\n", - "\n", - "For more direct control, a manual, magnitude based approach can be used. If this method is chosen or appropriate, it is highly recommended to look at these documentation:\n", - "- Scaling Toolbox https://idaes-pse.readthedocs.io/en/stable/reference_guides/scaling/scaling.html\n", - "- Scaling Workshop https://idaes-examples.readthedocs.io/en/latest/docs/scaling/scaler_workshop_doc.html.\n", - "\n", - "In this example, we already imported the ``AutoScaler`` class in the beginning so we just create the ``autoscaler`` object and call the ``scale_model`` method on the model `m`." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.750407Z", - "start_time": "2025-06-26T20:17:04.060666Z" - } - }, - "source": [ - "autoscaler = AutoScaler()\n", - "autoscaler.scale_model(m)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 2\n", - "component keys that are not exported as part of the NL file. Skipping.\n" - ] - } - ], - "execution_count": 27 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4 Specifying the Model\n", - "### 4.1 Fixing feed conditions\n", - "\n", - "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.782300Z", - "start_time": "2025-06-26T20:17:04.758266Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "29\n" - ] - } - ], - "execution_count": 28 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.826906Z", - "start_time": "2025-06-26T20:17:04.822382Z" - } - }, - "source": [ - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(0.30)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I101.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.842149Z", - "start_time": "2025-06-26T20:17:04.838049Z" - } - }, - "source": [ - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"hydrogen\"].fix(0.30)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Vap\", \"methane\"].fix(0.02)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"benzene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"toluene\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"hydrogen\"].fix(1e-5)\n", - "m.fs.I102.flow_mol_phase_comp[0, \"Liq\", \"methane\"].fix(1e-5)\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 31 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4.2 Fixing unit model specifications\n", - "\n", - "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.869153Z", - "start_time": "2025-06-26T20:17:04.866639Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.fix(600)" - ], - "outputs": [], - "execution_count": 32 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.897870Z", - "start_time": "2025-06-26T20:17:04.892755Z" - } - }, - "source": [ - "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", - "\n", - "m.fs.R101.conv_constraint = Constraint(\n", - " expr=m.fs.R101.conversion * m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " == (\n", - " m.fs.R101.inlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " - m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"toluene\"]\n", - " )\n", - ")\n", - "\n", - "m.fs.R101.conversion.fix(0.75)\n", - "m.fs.R101.heat_duty.fix(0)" - ], - "outputs": [], - "execution_count": 33 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Flash conditions for F101 can be set as follows. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.928993Z", - "start_time": "2025-06-26T20:17:04.925962Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", - "m.fs.F101.deltaP.fix(0)" - ], - "outputs": [], - "execution_count": 34 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Set the conditions for Flash F102 to the following conditions:\n", - "
    \n", - "
  • T = 375 K
  • \n", - "
  • deltaP = -200000
  • \n", - "
\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.960513Z", - "start_time": "2025-06-26T20:17:04.957441Z" - } - }, - "source": [ - "# Todo: Set conditions for Flash F102" - ], - "outputs": [], - "execution_count": 35 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:04.983292Z", - "start_time": "2025-06-26T20:17:04.979234Z" - } - }, - "source": [ - "m.fs.F102.vap_outlet.temperature.fix(375)\n", - "m.fs.F102.deltaP.fix(-200000)" - ], - "outputs": [], - "execution_count": 36 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.010085Z", - "start_time": "2025-06-26T20:17:05.007330Z" - } - }, - "source": [ - "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", - "m.fs.C101.outlet.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 37 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.029655Z", - "start_time": "2025-06-26T20:17:05.025814Z" - } - }, - "source": [ - "# Todo: print the degrees of freedom" - ], - "outputs": [], - "execution_count": 38 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.070096Z", - "start_time": "2025-06-26T20:17:05.046307Z" - } - }, - "source": [ - "print(degrees_of_freedom(m))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "execution_count": 39 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.114892Z", - "start_time": "2025-06-26T20:17:05.112840Z" - } - }, - "source": [], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5 Initializing the Model\n", - "\n", - "\n", - "\n", - "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear\u2010stream method is necessary because it \u201cbreaks\u201d this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization\u2014and ultimately steady\u2010state convergence\u2014impossible.\n", - "\n", - "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", - "\n", - "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", - "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.137429Z", - "start_time": "2025-06-26T20:17:05.132086Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.151129Z", - "start_time": "2025-06-26T20:17:05.147972Z" - } - }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { - "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.173772Z", - "start_time": "2025-06-26T20:17:05.170619Z" - } - }, - "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", - "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.228588Z", - "start_time": "2025-06-26T20:17:05.223424Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.02,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.266556Z", - "start_time": "2025-06-26T20:17:05.263086Z" - } - }, - "source": [ - "def function(unit):\n", - " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", - " except InitializationError:\n", - " solver = get_solver()\n", - " solver.solve(unit)" - ], - "outputs": [], - "execution_count": 45 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.283753Z", - "start_time": "2025-06-26T20:17:05.281507Z" - } - }, - "source": [ - "# seq.run(m, function)" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 5.2 Manual Propagation Method\n", - "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.310090Z", - "start_time": "2025-06-26T20:17:05.306928Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", - "\n", - "We will first ensure that are current degrees of freedom is still zero" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.352272Z", - "start_time": "2025-06-26T20:17:05.329055Z" - } - }, - "source": [ - "print(f\"The DOF is {degrees_of_freedom(m)} initially\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 initially\n" - ] - } - ], - "execution_count": 48 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.394094Z", - "start_time": "2025-06-26T20:17:05.363031Z" - } - }, - "source": [ - "m.fs.s03_expanded.deactivate()\n", - "\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 10 after deactivating the tear stream\n" - ] - } - ], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:05.473532Z", - "start_time": "2025-06-26T20:17:05.422203Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5,\n", - " (0, \"Liq\", \"toluene\"): 0.30,\n", - " (0, \"Liq\", \"methane\"): 1e-5,\n", - " (0, \"Liq\", \"hydrogen\"): 1e-5,\n", - " (0, \"Vap\", \"benzene\"): 1e-5,\n", - " (0, \"Vap\", \"toluene\"): 1e-5,\n", - " (0, \"Vap\", \"methane\"): 0.5,\n", - " (0, \"Vap\", \"hydrogen\"): 0.5,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", - "\n", - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "\n", - "DOF_initial = degrees_of_freedom(m)\n", - "print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after providing the initial guesses\n" - ] - } - ], - "execution_count": 50 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.120417Z", - "start_time": "2025-06-26T20:17:05.497326Z" - } - }, - "source": [ - "m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "propagate_state(\n", - " m.fs.s07\n", - ") # Establish connection between First Flash Unit and Second Flash Unit\n", - "m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "propagate_state(\n", - " m.fs.s10\n", - ") # Establish connection between Second Flash Unit and Benzene Product\n", - "propagate_state(\n", - " m.fs.s11\n", - ") # Establish connection between Second Flash Unit and Toluene Product\n", - "propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-06-26 13:17:05 [INFO] idaes.init.fs.H101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.H101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.R101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.F101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.C101.control_volume.properties_out: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I101.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.I102.properties: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_1_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_2_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.inlet_3_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n", - "2025-06-26 13:17:06 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_in: Initialization Complete\n", - "2025-06-26 13:17:07 [INFO] idaes.init.fs.F102.control_volume.properties_out: Initialization Complete\n" - ] - } - ], - "execution_count": 51 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.215113Z", - "start_time": "2025-06-26T20:17:07.128960Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 40\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=300\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp1xkj7htw_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1112\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 999\n", - "\n", - "Total number of variables............................: 380\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 186\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 380\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 4.73e+04 4.13e+02 -1.0 2.97e+03 - 9.24e-01 1.40e-01h 1\n", - " 2 0.0000000e+00 3.47e+04 1.79e+03 -1.0 4.13e+02 - 9.96e-01 4.70e-01h 1\n", - " 3 0.0000000e+00 2.08e+04 1.61e+05 -1.0 2.22e+02 - 1.00e+00 5.03e-01h 1\n", - " 4 0.0000000e+00 3.88e+03 2.20e+09 -1.0 1.09e+02 - 1.00e+00 9.80e-01h 1\n", - " 5 0.0000000e+00 2.07e+03 3.77e+08 -1.0 1.71e+02 - 1.00e+00 4.67e-01h 2\n", - " 6 0.0000000e+00 1.36e+02 2.14e+09 -1.0 9.39e+01 - 1.00e+00 9.62e-01h 1\n", - " 7 0.0000000e+00 3.87e+01 6.04e+08 -1.0 4.82e+00 - 1.00e+00 1.00e+00h 1\n", - " 8 0.0000000e+00 1.46e-02 3.71e+05 -1.0 5.17e-03 - 1.00e+00 1.00e+00h 1\n", - " 9 0.0000000e+00 3.73e-08 7.83e-02 -1.0 5.17e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 9\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 3.7252902984619141e-08\n", - "\n", - "\n", - "Number of objective function evaluations = 12\n", - "Number of objective gradient evaluations = 10\n", - "Number of equality constraint evaluations = 12\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 10\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 9\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.010\n", - "Total CPU secs in NLP function evaluations = 0.000\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 52 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.250825Z", - "start_time": "2025-06-26T20:17:07.225571Z" - } - }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The DOF is 0 after unfixing the values and reactivating the tear stream\n" - ] - } - ], - "execution_count": 53 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6 Solving the Model" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.264286Z", - "start_time": "2025-06-26T20:17:07.261233Z" - } - }, - "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 1000,\n", - " \"tol\": 1e-8,\n", - "}" - ], - "outputs": [], - "execution_count": 54 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", - "\n", - "solver = get_solver(solver_options=optarg)
\n", - "results = solver.solve(m, tee=True)\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code.\n", - "
\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.289757Z", - "start_time": "2025-06-26T20:17:07.286635Z" - } - }, - "source": [ - "# Create the solver object\n", - "\n", - "# Solve the model" - ], - "outputs": [], - "execution_count": 55 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.696793Z", - "start_time": "2025-06-26T20:17:07.319999Z" - } - }, - "source": [ - "# Create the solver object\n", - "solver = get_solver(solver_options=optarg)\n", - "\n", - "# Solve the model\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 30\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp4mgrdyp8_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1163\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 1062\n", - "\n", - "Total number of variables............................: 390\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 196\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 8.67e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 0.0000000e+00 7.60e+04 9.94e+02 -1.0 1.40e+04 - 2.13e-02 3.48e-02h 1\n", - " 2 0.0000000e+00 5.95e+04 6.95e+03 -1.0 1.61e+04 - 3.13e-01 2.14e-02h 1\n", - " 3 0.0000000e+00 5.61e+04 6.09e+05 -1.0 1.49e+04 - 2.24e-01 1.97e-03h 1\n", - " 4 0.0000000e+00 5.61e+04 1.49e+08 -1.0 1.47e+04 - 2.03e-01 1.16e-05h 2\n", - " 5r 0.0000000e+00 5.61e+04 1.00e+03 0.1 0.00e+00 - 0.00e+00 3.65e-07R 6\n", - " 6r 0.0000000e+00 8.49e+04 9.54e+03 0.1 1.13e+03 - 2.61e-04 1.22e-03f 1\n", - " 7r 0.0000000e+00 8.45e+04 1.07e+04 0.1 8.37e+02 - 1.35e-03 1.15e-03f 1\n", - " 8r 0.0000000e+00 8.55e+04 9.03e+03 0.1 5.92e+02 - 3.94e-03 4.57e-03f 1\n", - " 9r 0.0000000e+00 8.66e+04 1.26e+04 0.1 2.01e+02 - 1.12e-02 9.36e-03f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10r 0.0000000e+00 8.68e+04 1.27e+04 0.1 2.05e+02 - 3.33e-02 1.85e-02f 1\n", - " 11r 0.0000000e+00 8.54e+04 1.53e+04 0.1 3.02e+02 - 5.49e-02 4.32e-02f 1\n", - " 12r 0.0000000e+00 1.34e+05 3.94e+03 0.1 2.99e+02 - 1.78e-01 6.41e-02f 1\n", - " 13r 0.0000000e+00 2.25e+05 1.12e+04 0.1 1.07e+01 - 2.06e-01 1.82e-01f 1\n", - " 14r 0.0000000e+00 2.75e+05 7.72e+03 0.1 6.66e+00 - 4.10e-01 4.96e-01f 1\n", - " 15r 0.0000000e+00 3.07e+06 5.98e+03 0.1 9.95e+00 - 2.39e-01 8.98e-01f 1\n", - " 16r 0.0000000e+00 5.95e+05 2.87e+03 0.1 6.81e+00 - 6.20e-01 1.00e+00f 1\n", - " 17r 0.0000000e+00 5.41e+05 3.10e+07 0.1 3.06e+00 2.0 6.95e-01 1.00e+00f 1\n", - " 18r 0.0000000e+00 2.82e+06 1.25e+07 0.1 1.67e+01 - 5.36e-01 5.96e-01f 1\n", - " 19r 0.0000000e+00 5.52e+04 2.79e+03 0.1 1.55e+01 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20r 0.0000000e+00 4.83e+04 1.35e+02 0.1 6.33e+00 - 1.00e+00 1.00e+00H 1\n", - " 21r 0.0000000e+00 4.83e+04 3.81e+00 0.1 1.45e+00 - 1.00e+00 1.00e+00H 1\n", - " 22r 0.0000000e+00 1.42e+05 9.56e+02 -1.3 1.01e+01 - 9.12e-01 5.38e-01f 1\n", - " 23r 0.0000000e+00 7.36e+04 6.87e+02 -1.3 5.78e+01 - 1.00e+00 6.19e-01f 1\n", - " 24r 0.0000000e+00 1.40e+04 1.55e+02 -1.3 3.64e+01 - 1.00e+00 9.27e-01f 1\n", - " 25r 0.0000000e+00 7.49e+03 8.20e+02 -1.3 9.10e-03 1.5 5.98e-01 1.00e+00f 1\n", - " 26r 0.0000000e+00 7.63e+03 2.36e+01 -1.3 6.03e-03 1.0 1.00e+00 1.00e+00h 1\n", - " 27r 0.0000000e+00 7.80e+03 6.01e+01 -1.3 4.10e+00 - 1.00e+00 1.00e+00h 1\n", - " 28r 0.0000000e+00 7.81e+03 6.15e-01 -1.3 1.56e-01 - 1.00e+00 1.00e+00h 1\n", - " 29r 0.0000000e+00 1.93e+04 4.65e+02 -2.0 3.57e+00 - 8.79e-01 9.94e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30r 0.0000000e+00 1.52e+04 1.38e+01 -2.0 1.98e-02 0.6 1.00e+00 1.00e+00h 1\n", - " 31r 0.0000000e+00 9.33e+03 6.58e-01 -2.0 5.30e-02 0.1 1.00e+00 1.00e+00h 1\n", - " 32r 0.0000000e+00 8.48e+03 6.52e-02 -2.0 1.58e-01 -0.4 1.00e+00 1.00e+00h 1\n", - " 33r 0.0000000e+00 8.55e+03 3.58e+01 -3.0 4.72e-01 -0.9 8.63e-01 8.67e-01f 1\n", - " 34r 0.0000000e+00 8.52e+03 1.66e+02 -3.0 2.21e+00 -1.3 1.00e+00 1.00e+00f 1\n", - " 35r 0.0000000e+00 1.11e+05 4.09e+03 -3.0 5.09e+02 - 4.37e-01 1.06e-01f 1\n", - " 36r 0.0000000e+00 8.12e+03 1.38e+03 -3.0 1.15e-02 0.9 8.34e-01 2.73e-01h 1\n", - " 37r 0.0000000e+00 8.08e+03 3.10e+03 -3.0 4.55e+02 - 7.85e-01 1.99e-02f 1\n", - " 38r 0.0000000e+00 3.10e+04 6.81e+02 -3.0 3.03e-02 0.4 6.77e-01 1.00e+00h 1\n", - " 39r 0.0000000e+00 3.75e+04 1.12e+03 -3.0 4.46e+02 - 4.37e-01 1.48e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 40r 0.0000000e+00 7.80e+03 5.24e+02 -3.0 2.79e-02 -0.1 4.75e-01 1.00e+00h 1\n", - " 41r 0.0000000e+00 2.73e+04 9.04e+02 -3.0 3.81e+02 - 7.50e-01 2.89e-01f 1\n", - " 42r 0.0000000e+00 1.22e+05 1.82e+02 -3.0 2.70e+02 - 9.14e-01 1.00e+00f 1\n", - " 43r 0.0000000e+00 1.32e+04 8.10e+00 -3.0 1.88e+00 - 1.00e+00 1.00e+00h 1\n", - " 44r 0.0000000e+00 6.37e+03 6.48e-02 -3.0 6.26e-01 - 1.00e+00 1.00e+00h 1\n", - " 45r 0.0000000e+00 6.37e+03 4.22e-05 -3.0 5.86e-02 - 1.00e+00 1.00e+00h 1\n", - " 46r 0.0000000e+00 6.36e+03 5.53e+01 -6.8 1.94e+00 - 8.53e-01 8.35e-01f 1\n", - " 47r 0.0000000e+00 5.83e+03 6.40e+02 -6.8 4.62e+04 - 6.58e-01 2.50e-02f 1\n", - " 48r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.64e+04 - 9.35e-06 7.76e-03f 1\n", - " 49r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 2.09e-09 2.12e-05f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 50r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.67e+04 - 5.33e-07 1.85e-04f 1\n", - " 51r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.47e+04 - 1.89e-06 5.75e-05f 1\n", - " 52r 0.0000000e+00 5.66e+03 6.33e+02 -6.8 4.62e+04 - 2.56e-06 2.01e-05f 1\n", - " 53r 0.0000000e+00 5.66e+03 8.24e+02 -6.8 4.45e+04 - 7.89e-01 2.33e-06f 1\n", - " 54r 0.0000000e+00 5.62e+03 8.31e+02 -6.8 2.03e+04 - 6.75e-01 2.38e-03f 1\n", - " 55r 0.0000000e+00 3.80e+05 4.94e+02 -6.8 2.02e+04 - 8.17e-01 3.20e-01f 1\n", - " 56r 0.0000000e+00 3.61e+05 4.70e+02 -6.8 8.06e+03 - 4.92e-01 4.86e-02f 1\n", - " 57r 0.0000000e+00 3.06e+05 5.51e+02 -6.8 7.95e+03 - 1.00e+00 7.27e-01f 1\n", - " 58r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 5.98e+03 - 2.07e-02 3.59e-01h 1\n", - " 59r 0.0000000e+00 2.42e+05 3.80e+02 -6.8 3.44e+03 - 0.00e+00 3.94e-07R 2\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 60r 0.0000000e+00 1.78e+05 6.03e+02 -6.8 4.37e-01 -0.5 4.32e-01 2.67e-01f 1\n", - " 61r 0.0000000e+00 1.13e+05 5.24e+02 -6.8 1.69e+00 -1.0 1.04e-03 3.69e-01f 1\n", - " 62r 0.0000000e+00 1.13e+05 4.74e+02 -6.8 5.74e-01 -1.5 1.85e-01 2.82e-03f 1\n", - " 63r 0.0000000e+00 1.13e+05 6.65e+02 -6.8 1.14e+01 -2.0 1.45e-01 4.86e-06f 1\n", - " 64r 0.0000000e+00 9.04e+04 1.05e+03 -6.8 9.82e+00 -2.4 4.47e-01 1.98e-01f 1\n", - " 65r 0.0000000e+00 9.73e+04 2.23e+03 -6.8 4.15e+04 - 2.64e-02 2.25e-02f 1\n", - " 66r 0.0000000e+00 9.70e+04 2.19e+03 -6.8 2.35e+01 -2.9 2.59e-08 3.35e-03f 1\n", - " 67r 0.0000000e+00 9.67e+04 2.35e+03 -6.8 9.17e+00 -3.4 7.85e-03 3.49e-03f 1\n", - " 68r 0.0000000e+00 9.64e+04 2.59e+03 -6.8 3.25e+00 -3.9 1.46e-02 2.50e-03f 1\n", - " 69r 0.0000000e+00 9.46e+04 2.55e+03 -6.8 9.75e+00 -4.4 3.24e-03 1.89e-02f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 70r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 3.03e+04 - 2.51e-03 3.04e-03f 1\n", - " 71r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 2.23e+02 -4.8 2.06e-08 4.19e-06f 1\n", - " 72r 0.0000000e+00 9.44e+04 3.58e+03 -6.8 1.58e+04 - 2.25e-07 5.97e-07f 1\n", - " 73r 0.0000000e+00 9.44e+04 3.77e+03 -6.8 1.93e+03 -5.3 9.48e-04 5.00e-06f 1\n", - " 74r 0.0000000e+00 9.39e+04 3.76e+03 -6.8 2.44e+03 - 3.17e-03 4.55e-03f 1\n", - " 75r 0.0000000e+00 9.33e+04 5.36e+03 -6.8 2.41e+03 - 6.76e-02 7.47e-03f 1\n", - " 76r 0.0000000e+00 8.99e+04 5.27e+03 -6.8 2.38e+03 - 3.77e-02 3.65e-02f 1\n", - " 77r 0.0000000e+00 6.19e+04 5.51e+03 -6.8 2.21e+03 - 2.42e-01 3.97e-01f 1\n", - " 78r 0.0000000e+00 1.88e+04 2.51e+03 -6.8 1.05e+03 - 6.24e-01 7.35e-01f 1\n", - " 79r 0.0000000e+00 1.88e+04 1.05e+03 -6.8 5.33e+02 - 6.28e-01 6.39e-04f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 80r 0.0000000e+00 1.81e+04 1.33e+03 -6.8 5.33e+02 - 1.61e-01 3.85e-02f 1\n", - " 81r 0.0000000e+00 1.30e+04 8.88e+02 -6.8 5.12e+02 - 3.53e-01 2.85e-01f 1\n", - " 82r 0.0000000e+00 9.29e+02 6.86e+02 -6.8 3.66e+02 - 1.77e-01 9.58e-01f 1\n", - " 83r 0.0000000e+00 6.16e+00 5.32e+02 -6.8 2.15e+01 - 1.39e-01 9.98e-01f 1\n", - " 84r 0.0000000e+00 6.02e+00 5.20e+02 -6.8 2.41e+00 - 1.22e-02 2.30e-02h 1\n", - " 85r 0.0000000e+00 5.97e+00 8.56e+02 -6.8 8.89e-01 - 1.00e+00 8.65e-03f 1\n", - " 86r 0.0000000e+00 1.86e-01 1.05e-02 -6.8 2.28e-01 - 1.00e+00 1.00e+00f 1\n", - " 87r 0.0000000e+00 8.17e-02 1.14e-08 -6.8 2.65e-05 - 1.00e+00 1.00e+00h 1\n", - " 88r 0.0000000e+00 8.17e-02 2.77e-01 -9.0 2.35e-03 - 1.00e+00 9.86e-01f 1\n", - " 89r 0.0000000e+00 9.32e+04 1.22e+02 -9.0 8.44e+03 - 2.04e-01 3.79e-01f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 90r 0.0000000e+00 6.57e+03 3.47e+01 -9.0 7.94e+02 - 1.00e+00 1.00e+00h 1\n", - " 91r 0.0000000e+00 4.97e+03 6.57e+01 -9.0 9.04e+02 - 1.00e+00 4.54e-01h 2\n", - " 92r 0.0000000e+00 3.57e+03 4.95e+01 -9.0 6.55e+02 - 1.00e+00 4.92e-01h 2\n", - " 93r 0.0000000e+00 5.50e+03 1.48e+01 -9.0 3.71e+02 - 1.00e+00 1.00e+00h 1\n", - " 94r 0.0000000e+00 6.99e+02 7.05e+00 -9.0 7.16e+00 - 1.00e+00 4.90e-01h 2\n", - " 95r 0.0000000e+00 9.09e+03 2.36e+01 -9.0 3.44e+00 - 1.00e+00 1.00e+00h 1\n", - " 96r 0.0000000e+00 3.02e+03 8.85e+00 -9.0 3.32e-02 - 1.00e+00 9.20e-01h 1\n", - " 97r 0.0000000e+00 4.13e+01 1.81e-01 -9.0 7.94e-04 - 1.00e+00 1.00e+00h 1\n", - " 98r 0.0000000e+00 9.18e-03 6.71e-05 -9.0 8.29e-06 - 1.00e+00 1.00e+00h 1\n", - " 99r 0.0000000e+00 7.64e-06 7.98e-09 -9.0 5.10e-09 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 99\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 2.0579515874459978e-11 7.6442956924438477e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 122\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 123\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 102\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 99\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.200\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 56 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7 Analyze the results\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "noauto" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.732008Z", - "start_time": "2025-06-26T20:17:07.728387Z" - } - }, - "source": [ - "# m.fs.visualize(\"HDA-Flowsheet\")" - ], - "outputs": [], - "execution_count": 58 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.863289Z", - "start_time": "2025-06-26T20:17:07.761385Z" - } - }, - "source": [ - "m.fs.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Flowsheet : fs Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.2994e-07 1.2994e-07 1.0000e-08 0.20460 8.0000e-09 8.0000e-09 1.0000e-08 0.062620 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.30000 1.0000e-05 0.30001 8.4151e-07 8.4151e-07 1.0000e-08 0.062520 8.0000e-09 8.0000e-09 1.0000e-08 0.032257 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-05 1.0000e-05 2.0008e-05 1.0000e-12 1.0000e-12 1.0000e-08 2.6712e-07 8.0000e-09 8.0000e-09 1.0000e-08 9.4877e-08 2.0000e-09\n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-05 1.0000e-05 0.11934 0.11936 0.35374 0.14915 1.0000e-08 0.11932 0.11932 0.14198 1.0000e-08 0.029829\n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-05 1.0000e-05 0.012508 0.31252 0.078129 0.015610 1.0000e-08 0.012488 0.012488 0.030264 1.0000e-08 0.0031219\n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-05 0.020000 1.0377 1.0377 1.2721 1.2721 1.0000e-08 1.0177 1.0177 1.8224e-07 1.0000e-08 0.25442\n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-05 0.30000 0.56258 0.56260 0.32821 0.32821 1.0000e-08 0.26257 0.26257 1.8224e-07 1.0000e-08 0.065642\n", - " temperature kelvin 303.20 303.20 314.09 600.00 771.85 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", - "====================================================================================\n" - ] - } - ], - "execution_count": 59 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What is the total operating cost?" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:07.883053Z", - "start_time": "2025-06-26T20:17:07.876775Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 419122.3387221198\n" - ] - } - ], - "execution_count": 60 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.049906Z", - "start_time": "2025-06-26T20:17:08.024951Z" - } - }, - "source": [ - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7352.5 : watt : False : (None, None)\n", - " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.20460 1.0000e-08 0.062620 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.062520 1.0000e-08 0.032257 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.6712e-07 1.0000e-08 9.4877e-08 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.14198 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.030264 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.8224e-07 1.0000e-08 \n", - " temperature kelvin 325.00 375.00 375.00 \n", - " pressure pascal 3.5000e+05 1.5000e+05 1.5000e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8242962943938487\n" - ] - } - ], - "execution_count": 62 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.106226Z", - "start_time": "2025-06-26T20:17:08.088181Z" - } - }, - "source": [ - "from idaes.core.util.tables import (\n", - " create_stream_table_dataframe,\n", - " stream_table_dataframe_to_string,\n", - ")\n", - "\n", - "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", - "print(stream_table_dataframe_to_string(st))" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Units Reactor Light Gases\n", - "flow_mol_phase_comp ('Liq', 'benzene') mole / second 1.2994e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'toluene') mole / second 8.4151e-07 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 \n", - "flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.35374 0.14915 \n", - "flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.078129 0.015610 \n", - "flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2721 1.2721 \n", - "flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.32821 0.32821 \n", - "temperature kelvin 771.85 325.00 \n", - "pressure pascal 3.5000e+05 3.5000e+05 \n" - ] - } - ], - "execution_count": 64 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8 Optimization\n", - "\n", - "\n", - "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", - "\n", - "Let us try to minimize this cost such that:\n", - "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", - "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", - "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", - "\n", - "For this problem, our decision variables are as follows:\n", - "- H101 outlet temperature\n", - "- R101 cooling duty provided\n", - "- F101 outlet temperature\n", - "- F102 outlet temperature\n", - "- F102 deltaP in the flash tank\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us declare our objective function for this problem. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.138832Z", - "start_time": "2025-06-26T20:17:08.135122Z" - } - }, - "source": [ - "m.fs.objective = Objective(expr=m.fs.operating_cost)" - ], - "outputs": [], - "execution_count": 65 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.178125Z", - "start_time": "2025-06-26T20:17:08.175210Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature.unfix()\n", - "m.fs.R101.heat_duty.unfix()\n", - "m.fs.F101.vap_outlet.temperature.unfix()\n", - "m.fs.F102.vap_outlet.temperature.unfix()" - ], - "outputs": [], - "execution_count": 66 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.197104Z", - "start_time": "2025-06-26T20:17:08.193860Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102" - ], - "outputs": [], - "execution_count": 67 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.224222Z", - "start_time": "2025-06-26T20:17:08.221218Z" - } - }, - "source": [ - "# Todo: Unfix deltaP for F102\n", - "m.fs.F102.deltaP.unfix()" - ], - "outputs": [], - "execution_count": 68 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to set bounds on these decision variables to values shown below:\n", - "\n", - " - H101 outlet temperature [500, 600] K\n", - " - R101 outlet temperature [600, 800] K\n", - " - F101 outlet temperature [298, 450] K\n", - " - F102 outlet temperature [298, 450] K\n", - " - F102 outlet pressure [105000, 110000] Pa\n", - "\n", - "Let us first set the variable bound for the H101 outlet temperature as shown below:" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.291933Z", - "start_time": "2025-06-26T20:17:08.289122Z" - } - }, - "source": [ - "m.fs.H101.outlet.temperature[0].setlb(500)\n", - "m.fs.H101.outlet.temperature[0].setub(600)" - ], - "outputs": [], - "execution_count": 70 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, set the variable bound for the R101 outlet temperature.\n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.321925Z", - "start_time": "2025-06-26T20:17:08.318981Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature" - ], - "outputs": [], - "execution_count": 71 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.350491Z", - "start_time": "2025-06-26T20:17:08.346275Z" - } - }, - "source": [ - "# Todo: Set the bounds for reactor outlet temperature\n", - "m.fs.R101.outlet.temperature[0].setlb(600)\n", - "m.fs.R101.outlet.temperature[0].setub(800)" - ], - "outputs": [], - "execution_count": 72 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us fix the bounds for the rest of the decision variables. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.380399Z", - "start_time": "2025-06-26T20:17:08.376824Z" - } - }, - "source": [ - "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", - "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", - "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", - "m.fs.F102.vap_outlet.pressure[0].setub(110000)" - ], - "outputs": [], - "execution_count": 73 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.404523Z", - "start_time": "2025-06-26T20:17:08.401091Z" - } - }, - "source": [ - "m.fs.overhead_loss = Constraint(\n", - " expr=m.fs.F101.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - " <= 0.20 * m.fs.R101.outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"]\n", - ")" - ], - "outputs": [], - "execution_count": 74 - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [ - "exercise" - ] - }, - "source": [ - "
\n", - "Inline Exercise:\n", - "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", - "\n", - "Use Shift+Enter to run the cell once you have typed in your code. \n", - "
" - ] - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "exercise" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.434557Z", - "start_time": "2025-06-26T20:17:08.431016Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint" - ], - "outputs": [], - "execution_count": 75 - }, - { - "cell_type": "code", - "metadata": { - "tags": [ - "solution" - ], - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.462910Z", - "start_time": "2025-06-26T20:17:08.459216Z" - } - }, - "source": [ - "# Todo: Add minimum product flow constraint\n", - "m.fs.product_flow = Constraint(\n", - " expr=m.fs.F102.vap_outlet.flow_mol_phase_comp[0, \"Vap\", \"benzene\"] >= 0.15\n", - ")" - ], - "outputs": [], - "execution_count": 76 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.495878Z", - "start_time": "2025-06-26T20:17:08.492876Z" - } - }, - "source": [ - "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" - ], - "outputs": [], - "execution_count": 77 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "We have now defined the optimization problem and we are now ready to solve this problem. \n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.669116Z", - "start_time": "2025-06-26T20:17:08.518790Z" - } - }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING: model contains export suffix 'scaling_factor' that contains 25\n", - "component keys that are not exported as part of the NL file. Skipping.\n", - "Ipopt 3.13.2: nlp_scaling_method=user-scaling\n", - "tol=1e-08\n", - "max_iter=1000\n", - "option_file_name=C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmp6z6_l7re_ipopt.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma27.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 1191\n", - "Number of nonzeros in inequality constraint Jacobian.: 5\n", - "Number of nonzeros in Lagrangian Hessian.............: 1065\n", - "\n", - "Total number of variables............................: 395\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 199\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 390\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.1912234e+05 2.99e+05 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - " 1 4.1133558e+05 2.94e+05 6.94e+00 -1.0 6.60e+07 - 2.90e-06 1.05e-05f 1\n", - " 2 3.2484037e+05 1.80e+06 6.94e+00 -1.0 2.33e+09 - 2.95e-07 4.87e-06f 1\n", - " 3 3.0318192e+05 1.92e+06 6.94e+00 -1.0 6.90e+08 - 1.70e-05 4.13e-06f 1\n", - " 4 3.0263181e+05 1.92e+06 2.20e+01 -1.0 1.43e+07 - 8.92e-05 1.73e-05f 1\n", - " 5 3.0137102e+05 1.92e+06 4.38e+01 -1.0 8.74e+06 - 6.63e-05 1.11e-04f 1\n", - " 6 3.0058759e+05 1.92e+06 1.37e+03 -1.0 2.21e+07 - 8.59e-06 2.17e-04f 1\n", - " 7 3.0058113e+05 1.92e+06 7.51e+04 -1.0 3.24e+05 - 2.49e-01 1.77e-04f 1\n", - " 8 3.0317331e+05 1.38e+06 2.08e+05 -1.0 4.00e+04 - 9.62e-01 2.82e-01h 1\n", - " 9 3.0372038e+05 1.26e+06 1.91e+05 -1.0 2.87e+04 - 1.50e-01 8.31e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.0372988e+05 1.26e+06 9.32e+05 -1.0 2.63e+04 - 1.00e+00 1.51e-03h 1\n", - " 11 3.0386427e+05 1.24e+06 1.90e+07 -1.0 2.63e+04 - 1.00e+00 2.03e-02h 2\n", - " 12 3.0393928e+05 1.22e+06 7.46e+08 -1.0 2.58e+04 - 1.00e+00 1.15e-02h 2\n", - " 13 3.0397909e+05 1.21e+06 4.87e+10 -1.0 2.55e+04 - 1.00e+00 6.13e-03h 2\n", - " 14 3.0399961e+05 1.21e+06 5.05e+12 -1.0 2.53e+04 - 1.00e+00 3.17e-03h 2\n", - " 15 3.0401009e+05 1.21e+06 7.59e+14 -1.0 2.52e+04 - 1.00e+00 1.62e-03h 2\n", - " 16 3.0958447e+05 1.42e+06 9.07e+17 -1.0 2.51e+04 - 9.30e-01 9.31e-01h 1\n", - " 17 3.1108598e+05 7.50e+05 1.56e+17 -1.0 1.79e+03 - 1.76e-01 4.75e-01h 1\n", - " 18 3.1165423e+05 7.60e+03 1.25e+17 -1.0 9.40e+02 - 3.15e-02 9.90e-01H 1\n", - " 19 3.1168549e+05 7.39e+03 1.21e+17 -1.0 3.08e+02 - 1.00e+00 2.76e-02h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.0439929e+05 1.37e+03 1.61e+18 -1.0 1.81e+03 - 1.00e+00 9.75e-01f 1\n", - "WARNING: Problem in step computation; switching to emergency mode.\n", - " 21r 3.0439929e+05 1.37e+03 1.00e+03 -1.0 0.00e+00 20.0 0.00e+00 0.00e+00R 1\n", - " 22r 3.0442914e+05 1.83e+03 4.00e+06 -1.0 6.01e+02 - 4.63e-02 7.04e-03f 1\n", - " 23 3.0442888e+05 1.83e+03 3.42e+06 -1.0 8.14e+03 - 3.34e-01 2.84e-06f 2\n", - " 24 3.1274487e+05 1.62e+03 7.05e+07 -1.0 2.05e+03 - 9.80e-01 1.00e+00h 1\n", - " 25 3.1278608e+05 1.10e+02 5.31e+08 -1.0 1.68e+01 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1278641e+05 2.09e+01 1.01e+08 -1.0 1.92e-01 - 1.00e+00 5.00e-01h 2\n", - " 27 3.1278657e+05 5.78e+00 2.78e+07 -1.0 9.59e-02 - 1.00e+00 5.00e-01h 2\n", - " 28 3.1278674e+05 4.69e+00 2.27e+07 -1.0 4.80e-02 - 1.00e+00 1.00e+00h 1\n", - " 29 3.1278674e+05 6.41e-05 2.50e+02 -1.0 1.25e-06 - 1.00e+00 1.00e+00h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 30 3.1278634e+05 3.48e-05 1.57e+05 -3.8 1.36e+00 - 1.00e+00 1.00e+00f 1\n", - " 31 3.1278634e+05 2.24e-08 7.47e-04 -3.8 3.85e-04 - 1.00e+00 1.00e+00f 1\n", - " 32 3.1278634e+05 2.24e-08 3.58e-01 -8.6 2.04e-03 - 1.00e+00 1.00e+00f 1\n", - " 33 3.1278634e+05 2.98e-08 4.40e-05 -8.6 8.66e-10 - 1.00e+00 1.00e+00h 1\n", - " 34 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.17e-08 - 1.00e+00 1.00e+00h 1\n", - " 35 3.1278634e+05 1.49e-08 4.40e-05 -9.0 2.91e-11 - 1.00e+00 1.00e+00h 1\n", - " 36 3.1278634e+05 1.49e-08 4.40e-05 -9.0 8.46e-11 - 1.00e+00 1.00e+00h 1\n", - " 37 3.1278634e+05 2.98e-08 4.40e-05 -9.0 1.06e-10 - 1.00e+00 1.00e+00h 1\n", - " 38 3.1278634e+05 2.98e-08 4.40e-05 -9.0 4.00e-11 - 1.00e+00 2.50e-01h 3\n", - " 39 3.1278634e+05 1.49e-08 1.82e-05 -9.0 3.37e-11 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 39\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1278633834066644e+05 3.1278633834066644e+05\n", - "Dual infeasibility......: 1.8179731622468097e-05 3.6359463244936194e-05\n", - "Constraint violation....: 4.1159031748919956e-11 1.4901161193847656e-08\n", - "Complementarity.........: 9.2191617461622095e-10 9.2191617461622095e-10\n", - "Overall NLP error.......: 6.7531650843155892e-09 3.6359463244936194e-05\n", - "\n", - "\n", - "Number of objective function evaluations = 62\n", - "Number of objective gradient evaluations = 39\n", - "Number of equality constraint evaluations = 62\n", - "Number of inequality constraint evaluations = 62\n", - "Number of equality constraint Jacobian evaluations = 40\n", - "Number of inequality constraint Jacobian evaluations = 40\n", - "Number of Lagrangian Hessian evaluations = 39\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.054\n", - "Total CPU secs in NLP function evaluations = 0.008\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 78 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 8.1 Optimization Results\n", - "\n", - "Display the results and product specifications" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.738912Z", - "start_time": "2025-06-26T20:17:08.700529Z" - } - }, - "source": [ - "print(\"operating cost = $\", value(m.fs.operating_cost))\n", - "\n", - "print()\n", - "print(\"Product flow rate and purity in F102\")\n", - "\n", - "m.fs.F102.report()\n", - "\n", - "print()\n", - "print(\"benzene purity = \", value(m.fs.purity))\n", - "\n", - "print()\n", - "print(\"Overhead loss in F101\")\n", - "m.fs.F101.report()" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "operating cost = $ 312786.3383406665\n", - "\n", - "Product flow rate and purity in F102\n", - "\n", - "====================================================================================\n", - "Unit : fs.F102 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8377.0 : watt : False : (None, None)\n", - " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 0.21743 1.0000e-08 0.067425 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 0.070695 1.0000e-08 0.037507 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 2.8812e-07 1.0000e-08 1.0493e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 1.0000e-08 0.15000 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 1.0000e-08 0.033189 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 1.0000e-08 1.9319e-07 1.0000e-08 \n", - " temperature kelvin 301.88 362.93 362.93 \n", - " pressure pascal 3.5000e+05 1.0500e+05 1.0500e+05 \n", - "====================================================================================\n", - "\n", - "benzene purity = 0.8188276578115862\n", - "\n", - "Overhead loss in F101\n", - "\n", - "====================================================================================\n", - "Unit : fs.F101 Time: 0.0\n", - "------------------------------------------------------------------------------------\n", - " Unit Performance\n", - "\n", - " Variables: \n", - "\n", - " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -56353. : watt : False : (None, None)\n", - " Pressure Change : 0.0000 : pascal : True : (None, None)\n", - "\n", - "------------------------------------------------------------------------------------\n", - " Stream Table\n", - " Units Inlet Vapor Outlet Liquid Outlet\n", - " flow_mol_phase_comp ('Liq', 'benzene') mole / second 4.3534e-08 1.0000e-08 0.21743 \n", - " flow_mol_phase_comp ('Liq', 'toluene') mole / second 7.5866e-07 1.0000e-08 0.070695 \n", - " flow_mol_phase_comp ('Liq', 'methane') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Liq', 'hydrogen') mole / second 1.0000e-12 1.0000e-08 2.8812e-07 \n", - " flow_mol_phase_comp ('Vap', 'benzene') mole / second 0.27178 0.054356 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'toluene') mole / second 0.076085 0.0053908 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'methane') mole / second 1.2414 1.2414 1.0000e-08 \n", - " flow_mol_phase_comp ('Vap', 'hydrogen') mole / second 0.35887 0.35887 1.0000e-08 \n", - " temperature kelvin 696.11 301.88 301.88 \n", - " pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 \n", - "====================================================================================\n" - ] - } - ], - "execution_count": 80 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display optimal values for the decision variables" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-26T20:17:08.793956Z", - "start_time": "2025-06-26T20:17:08.789446Z" - } - }, - "source": [ - "print(\n", - " f\"\"\"Optimal Values:\n", - "\n", - "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", - "\n", - "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", - "\n", - "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", - "\n", - "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", - "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", - "\"\"\"\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Optimal Values:\n", - "\n", - "H101 outlet temperature = 500.000 K\n", - "\n", - "R101 outlet temperature = 696.112 K\n", - "\n", - "F101 outlet temperature = 301.878 K\n", - "\n", - "F102 outlet temperature = 362.935 K\n", - "F102 outlet pressure = 105000.000 Pa\n", - "\n" - ] - } - ], - "execution_count": 82 - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 3 + "cells": [ + { + "cell_type": "code", + "metadata": { + "tags": [ + "header", + "hide-cell" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:04.904828Z", + "start_time": "2025-11-20T21:46:04.900352Z" + } + }, + "source": [ + "###############################################################################\n", + "# The Institute for the Design of Advanced Energy Systems Integrated Platform\n", + "# Framework (idaes IP) was produced under the DOE Institute for the\n", + "# Design of Advanced Energy Systems (IDAES).\n", + "#\n", + "# Copyright (c) 2018-2023 by the software owners: The Regents of the\n", + "# University of California, through Lawrence Berkeley National Laboratory,\n", + "# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon\n", + "# University, West Virginia University Research Corporation, et al.\n", + "# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md\n", + "# for full copyright and license information.\n", + "###############################################################################" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# HDA Flowsheet Simulation and Optimization\n", + "\n", + "Author: Jaffer Ghouse
\n", + "Maintainer: Tanner Polley
\n", + "Updated: 2025-11-19\n", + "\n", + "## Learning outcomes\n", + "\n", + "\n", + "- Construct a steady-state flowsheet using the IDAES unit model library\n", + "- Connecting unit models in a flowsheet using Arcs\n", + "- Using the SequentialDecomposition tool to initialize a flowsheet with recycle\n", + "- Formulate and solve an optimization problem\n", + " - Defining an objective function\n", + " - Setting variable bounds\n", + " - Adding additional constraints\n", + "\n", + "\n", + "The general workflow of setting up an IDAES flowsheet is the following:\n", + "\n", + "     1 Importing Modules
\n", + "     2 Building a Model
\n", + "     3 Scaling the Model
\n", + "     4 Specifying the Model
\n", + "     5 Initializing the Model
\n", + "     6 Solving the Model
\n", + "     7 Analyzing and Visualizing the Results
\n", + "     8 Optimizing the Model
\n", + "\n", + "We will complete each of these steps as well as demonstrate analyses on this model through some examples and exercises.\n", + "\n", + "\n", + "## Problem Statement\n", + "\n", + "Hydrodealkylation is a chemical reaction that often involves reacting\n", + "an aromatic hydrocarbon in the presence of hydrogen gas to form a\n", + "simpler aromatic hydrocarbon devoid of functional groups. In this\n", + "example, toluene will be reacted with hydrogen gas at high temperatures\n", + " to form benzene via the following reaction:\n", + "\n", + "**C6H5CH3 + H2 → C6H6 + CH4**\n", + "\n", + "\n", + "This reaction is often accompanied by an equilibrium side reaction\n", + "which forms diphenyl, which we will neglect for this example.\n", + "\n", + "This example is based on the 1967 AIChE Student Contest problem as\n", + "present by Douglas, J.M., Chemical Design of Chemical Processes, 1988,\n", + "McGraw-Hill.\n", + "\n", + "The flowsheet that we will be using for this module is shown below with the stream conditions. We will be processing toluene and hydrogen to produce at least 370 TPY of benzene. As shown in the flowsheet, there are two flash tanks, F101 to separate out the non-condensibles and F102 to further separate the benzene-toluene mixture to improve the benzene purity. Note that typically a distillation column is required to obtain high purity benzene but that is beyond the scope of this workshop. The non-condensibles separated out in F101 will be partially recycled back to M101 and the rest will be either purged or combusted for power generation.We will assume ideal gas for this flowsheet. The properties required for this module are available in the same directory:\n", + "\n", + "- hda_ideal_VLE.py\n", + "- hda_reaction.py\n", + "\n", + "The state variables chosen for the property package are **flows of component by phase, temperature and pressure**. The components considered are: **toluene, hydrogen, benzene and methane**. Therefore, every stream has 8 flow variables, 1 temperature and 1 pressure variable. \n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 Importing Modules\n", + "### 1.1 Importing required Pyomo and IDAES components\n", + "\n", + "\n", + "To construct a flowsheet, we will need several components from the Pyomo and IDAES package. Let us first import the following components from Pyomo:\n", + "- Constraint (to write constraints)\n", + "- Var (to declare variables)\n", + "- ConcreteModel (to create the concrete model object)\n", + "- Expression (to evaluate values as a function of variables defined in the model)\n", + "- Objective (to define an objective function for optimization)\n", + "- SolverFactory (to solve the problem)\n", + "- TransformationFactory (to apply certain transformations)\n", + "- Arc (to connect two unit models)\n", + "- SequentialDecomposition (to initialize the flowsheet in a sequential mode)\n", + "\n", + "For further details on these components, please refer to the Pyomo documentation: https://Pyomo.readthedocs.io/en/stable/\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:05.294578Z", + "start_time": "2025-11-20T21:46:04.908296Z" + } + }, + "source": [ + "from pyomo.environ import (\n", + " Constraint,\n", + " Var,\n", + " ConcreteModel,\n", + " Expression,\n", + " Objective,\n", + " TransformationFactory,\n", + " value,\n", + ")\n", + "from pyomo.network import Arc, SequentialDecomposition" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From IDAES, we will be needing the FlowsheetBlock and the following unit models:\n", + "- Feed\n", + "- Mixer\n", + "- Heater\n", + "- StoichiometricReactor\n", + "- **Flash**\n", + "- Separator (splitter) \n", + "- PressureChanger\n", + "- Product" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:06.806301Z", + "start_time": "2025-11-20T21:46:05.297760Z" + } + }, + "source": [ + "from idaes.core import FlowsheetBlock" + ], + "outputs": [], + "execution_count": 3 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.936732Z", + "start_time": "2025-11-20T21:46:09.883054Z" + } + }, + "source": [ + "from idaes.models.unit_models import (\n", + " PressureChanger,\n", + " Mixer,\n", + " Separator as Splitter,\n", + " Heater,\n", + " StoichiometricReactor,\n", + " Feed,\n", + " Product,\n", + ")\n", + "from idaes.core.util.exceptions import InitializationError\n", + "import idaes.logger as idaeslog" + ], + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, import the remaining unit models highlighted in blue above and run the cell using `Shift+Enter` after typing in the code. \n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.952476Z", + "start_time": "2025-11-20T21:46:09.949367Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models" + ], + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.963041Z", + "start_time": "2025-11-20T21:46:09.957319Z" + } + }, + "source": [ + "# Todo: import flash model from idaes.models.unit_models\n", + "from idaes.models.unit_models import Flash" + ], + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will also be needing some utility tools to put together the flowsheet and calculate the degrees of freedom. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:09.976914Z", + "start_time": "2025-11-20T21:46:09.971944Z" + } + }, + "source": [ + "from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption\n", + "from idaes.core.util.model_statistics import degrees_of_freedom\n", + "\n", + "# Import idaes logger to set output levels\n", + "from idaes.core.solvers import get_solver" + ], + "outputs": [], + "execution_count": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 Importing required thermo and reaction package\n", + "\n", + "The final set of imports are to import the thermo and reaction package for the HDA process. We have created a custom thermo package that assumes Ideal Gas with support for VLE. \n", + "\n", + "The reaction package here is very simple as we will be using only a StochiometricReactor and the reaction package consists of the stochiometric coefficients for the reaction and the parameter for the heat of reaction. \n", + "\n", + "Let us import the following modules and they are in the same directory as this jupyter notebook:\n", + "
    \n", + "
  • hda_ideal_VLE as thermo_props
  • \n", + "
  • hda_reaction as reaction_props
  • \n", + "
\n", + "
" + ] + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.017098Z", + "start_time": "2025-11-20T21:46:09.981997Z" + } + }, + "cell_type": "code", + "source": [ + "from idaes.models.properties.modular_properties.base.generic_property import (\n", + " GenericParameterBlock,\n", + ")\n", + "from idaes.models.properties.modular_properties.base.generic_reaction import (\n", + " GenericReactionParameterBlock,\n", + ")\n", + "from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config\n", + "from idaes_examples.mod.hda.hda_reaction_modular import reaction_config" + ], + "outputs": [], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 Constructing the Flowsheet\n", + "\n", + "We have now imported all the components, unit models, and property modules we need to construct a flowsheet. Let us create a ConcreteModel and add the flowsheet block." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.031538Z", + "start_time": "2025-11-20T21:46:10.025904Z" + } + }, + "source": [ + "m = ConcreteModel()\n", + "m.fs = FlowsheetBlock(dynamic=False)" + ], + "outputs": [], + "execution_count": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now need to add the property packages to the flowsheet. Unlike Module 1, where we only had a thermo property package, for this flowsheet we will also need to add a reaction property package. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.066746Z", + "start_time": "2025-11-20T21:46:10.035131Z" + } + }, + "source": [ + "m.fs.thermo_params = GenericParameterBlock(**thermo_config)\n", + "m.fs.reaction_params = GenericReactionParameterBlock(\n", + " property_package=m.fs.thermo_params, **reaction_config\n", + ")" + ], + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Adding Unit Models\n", + "\n", + "Let us start adding the unit models we have imported to the flowsheet. Here, we are adding the Feed (assigned a name `I101` for Inlet), `Mixer` (assigned a name `M101`) and a `Heater` (assigned a name `H101`). Note that, all unit models need to be given a property package argument. In addition to that, there are several arguments depending on the unit model, please refer to the documentation for more details (https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/index.html). For example, the `Mixer` unit model here must be specified the number of inlets that it will take in and the `Heater` can have specific settings enabled such as `has_pressure_change` or `has_phase_equilibrium`." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.114600Z", + "start_time": "2025-11-20T21:46:10.071845Z" + } + }, + "source": [ + "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.M101 = Mixer(\n", + " property_package=m.fs.thermo_params,\n", + " num_inlets=3,\n", + ")\n", + "\n", + "m.fs.H101 = Heater(\n", + " property_package=m.fs.thermo_params,\n", + " has_pressure_change=False,\n", + " has_phase_equilibrium=True,\n", + ")" + ], + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now add the StoichiometricReactor(assign the name R101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"reaction_package\": m.fs.reaction_params
  • \n", + "
  • \"has_heat_of_reaction\": True
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.121709Z", + "start_time": "2025-11-20T21:46:10.119134Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above" + ], + "outputs": [], + "execution_count": 12 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.145853Z", + "start_time": "2025-11-20T21:46:10.127921Z" + } + }, + "source": [ + "# Todo: Add reactor with the specifications above\n", + "m.fs.R101 = StoichiometricReactor(\n", + " property_package=m.fs.thermo_params,\n", + " reaction_package=m.fs.reaction_params,\n", + " has_heat_of_reaction=True,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=False,\n", + ")" + ], + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Flash(assign the name F101) and pass the following arguments:\n", + "
    \n", + "
  • \"property_package\": m.fs.thermo_params
  • \n", + "
  • \"has_heat_transfer\": True
  • \n", + "
  • \"has_pressure_change\": False
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.167357Z", + "start_time": "2025-11-20T21:46:10.149935Z" + } + }, + "source": [ + "m.fs.F101 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add the Splitter(S101) with specific names for its output (purge and recycle), PressureChanger(C101) and the second Flash(F102)." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.211911Z", + "start_time": "2025-11-20T21:46:10.173255Z" + } + }, + "source": [ + "m.fs.S101 = Splitter(\n", + " property_package=m.fs.thermo_params,\n", + " ideal_separation=False,\n", + " outlet_list=[\"purge\", \"recycle\"],\n", + ")\n", + "\n", + "\n", + "m.fs.C101 = PressureChanger(\n", + " property_package=m.fs.thermo_params,\n", + " compressor=True,\n", + " thermodynamic_assumption=ThermodynamicAssumption.isothermal,\n", + ")\n", + "\n", + "m.fs.F102 = Flash(\n", + " property_package=m.fs.thermo_params,\n", + " has_heat_transfer=True,\n", + " has_pressure_change=True,\n", + ")" + ], + "outputs": [], + "execution_count": 15 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last, we will add the three Product blocks (P101, P102, P103). We use `Feed` blocks and `Product` blocks for convenience with reporting stream summaries and consistency" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.226989Z", + "start_time": "2025-11-20T21:46:10.216839Z" + } + }, + "source": [ + "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", + "\n", + "m.fs.P103 = Product(property_package=m.fs.thermo_params)" + ], + "outputs": [], + "execution_count": 16 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Connecting Unit Models using Arcs\n", + "\n", + "We have now added all the unit models we need to the flowsheet. However, we have not yet specified how the units are to be connected. To do this, we will be using the `Arc` which is a Pyomo component that takes in two arguments: `source` and `destination`. Let us connect the outlet of the inlets (I101, I102) to the inlet of the mixer (M101) and outlet of the mixer to the inlet of the heater(H101)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](HDA_flowsheet.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.235541Z", + "start_time": "2025-11-20T21:46:10.231058Z" + } + }, + "source": [ + "m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1)\n", + "m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2)\n", + "m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet)" + ], + "outputs": [], + "execution_count": 17 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, connect the H101 outlet to the R101 inlet using the cell above as a guide.\n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.245319Z", + "start_time": "2025-11-20T21:46:10.239913Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet" + ], + "outputs": [], + "execution_count": 18 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.254153Z", + "start_time": "2025-11-20T21:46:10.248481Z" + } + }, + "source": [ + "# Todo: Connect the H101 outlet to R101 inlet\n", + "m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet)" + ], + "outputs": [], + "execution_count": 19 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be connecting the rest of the flowsheet as shown below. Notice how the outlet names are different for the flash tanks F101 and F102 as they have a vapor and a liquid outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.264461Z", + "start_time": "2025-11-20T21:46:10.258555Z" + } + }, + "source": [ + "m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet)\n", + "m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet)\n", + "m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet)\n", + "m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet)\n", + "m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3)" + ], + "outputs": [], + "execution_count": 20 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Last we will connect the outlet streams to the inlets of the Product blocks (P101, P102, P103)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.274505Z", + "start_time": "2025-11-20T21:46:10.268918Z" + } + }, + "source": [ + "m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet)\n", + "m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet)\n", + "m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet)" + ], + "outputs": [], + "execution_count": 21 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have now connected the unit model block using the arcs. However, each of these arcs link to ports on the two unit models that are connected. In this case, the ports consist of the state variables that need to be linked between the unit models. Pyomo provides a convenient method to write these equality constraints for us between two ports and this is done as follows:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.303264Z", + "start_time": "2025-11-20T21:46:10.278714Z" + } + }, + "source": [ + "TransformationFactory(\"network.expand_arcs\").apply_to(m)" + ], + "outputs": [], + "execution_count": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Adding expressions to compute purity and operating costs\n", + "\n", + "In this section, we will add a few Expressions that allows us to evaluate the performance. Expressions provide a convenient way of calculating certain values that are a function of the variables defined in the model. For more details on Expressions, please refer to: https://pyomo.readthedocs.io/en/stable/explanation/modeling/network.html.\n", + "\n", + "For this flowsheet, we are interested in computing the purity of the product Benzene stream (i.e. the mole fraction) and the operating cost which is a sum of the cooling and heating cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first add an Expression to compute the mole fraction of benzene in the `vap_outlet` of F102 which is our product stream. Please note that the var flow_mol_phase_comp has the index - [time, phase, component]. As this is a steady-state flowsheet, the time index by default is 0. The valid phases are [\"Liq\", \"Vap\"]. Similarly the valid component list is [\"benzene\", \"toluene\", \"hydrogen\", \"methane\"]." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.312336Z", + "start_time": "2025-11-20T21:46:10.309074Z" + } + }, + "source": [ + "m.fs.purity = Expression(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " / (\n", + " m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + " + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")" + ], + "outputs": [], + "execution_count": 23 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let us add an expression to compute the cooling cost assuming a cost of 0.212E-4 $/kW. Note that cooling utility is required for the reactor (R101) and the first flash (F101). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.323538Z", + "start_time": "2025-11-20T21:46:10.318119Z" + } + }, + "source": [ + "m.fs.cooling_cost = Expression(\n", + " expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0])\n", + ")" + ], + "outputs": [], + "execution_count": 24 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Now, let us add an expression to compute the heating cost assuming the utility cost as follows:\n", + "
    \n", + "
  • 2.2E-4 dollars/kW for H101
  • \n", + "
  • 1.9E-4 dollars/kW for F102
  • \n", + "
\n", + "Note that the heat duty is in units of watt (J/s). " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.336983Z", + "start_time": "2025-11-20T21:46:10.328380Z" + } + }, + "source": [ + "m.fs.heating_cost = Expression(\n", + " expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0]\n", + ")" + ], + "outputs": [], + "execution_count": 25 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us now add an expression to compute the total operating cost per year which is basically the sum of the cooling and heating cost we defined above. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.345607Z", + "start_time": "2025-11-20T21:46:10.341996Z" + } + }, + "source": [ + "m.fs.operating_cost = Expression(\n", + " expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost))\n", + ")" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 Specifying the Model\n", + "### 4.1 Fixing feed conditions\n", + "\n", + "Let us first check how many degrees of freedom exist for this flowsheet using the `degrees_of_freedom` tool we imported earlier. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.376586Z", + "start_time": "2025-11-20T21:46:10.349694Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n" + ] + } + ], + "execution_count": 27 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.418520Z", + "start_time": "2025-11-20T21:46:10.414167Z" + } + }, + "source": [ + "F_liq_toluene = 0.30\n", + "F_liq_non_zero = 1e-5\n", + "\n", + "F_vap_I101 = F_liq_non_zero * 4\n", + "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "\n", + "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", + "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", + "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", + "m.fs.I101.temperature.fix(303.2)\n", + "m.fs.I101.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 29 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", + "
    \n", + "
  • FH2 = 0.30 mol/s
  • \n", + "
  • FCH4 = 0.02 mol/s
  • \n", + "
  • Remaining components = 1e-5 mol/s
  • \n", + "
  • T = 303.2 K
  • \n", + "
  • P = 350000 Pa
  • \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.429169Z", + "start_time": "2025-11-20T21:46:10.422052Z" + } + }, + "source": [ + "F_vap_hydrogen = 0.30\n", + "F_vap_methane = 0.020\n", + "\n", + "F_vap_non_zero = 1e-5\n", + "F_liq_non_zero = F_vap_non_zero\n", + "\n", + "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", + "F_liq_I102 = 2 * F_vap_non_zero\n", + "\n", + "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", + "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", + "\n", + "m.fs.I102.temperature.fix(303.2)\n", + "m.fs.I102.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Fixing unit model specifications\n", + "\n", + "Now that we have fixed our inlet feed conditions, we will now be fixing the operating conditions for the unit models in the flowsheet. Let us set set the H101 outlet temperature to 600 K. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.441145Z", + "start_time": "2025-11-20T21:46:10.433569Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.fix(600)" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the StoichiometricReactor, we have to define the conversion in terms of toluene. This requires us to create a new variable for specifying the conversion and adding a Constraint that defines the conversion with respect to toluene. The second degree of freedom for the reactor is to define the heat duty. In this case, let us assume the reactor to be adiabatic i.e. Q = 0. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.453419Z", + "start_time": "2025-11-20T21:46:10.445363Z" + } + }, + "source": [ + "m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1))\n", + "\n", + "m.fs.R101.conv_constraint = Constraint(\n", + " expr=m.fs.R101.conversion\n", + " * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"])\n", + " == (\n", + " m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp[\"Vap\", \"toluene\"]\n", + " - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"toluene\"\n", + " ]\n", + " )\n", + ")\n", + "\n", + "m.fs.R101.conversion.fix(0.75)\n", + "m.fs.R101.heat_duty.fix(0)" + ], + "outputs": [], + "execution_count": 32 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Flash conditions for F101 can be set as follows. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.463025Z", + "start_time": "2025-11-20T21:46:10.457476Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature.fix(325.0)\n", + "m.fs.F101.deltaP.fix(0)" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Set the conditions for Flash F102 to the following conditions:\n", + "
    \n", + "
  • T = 375 K
  • \n", + "
  • deltaP = -200000
  • \n", + "
\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.472509Z", + "start_time": "2025-11-20T21:46:10.467229Z" + } + }, + "source": [ + "# Todo: Set conditions for Flash F102" + ], + "outputs": [], + "execution_count": 34 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.482109Z", + "start_time": "2025-11-20T21:46:10.475567Z" + } + }, + "source": [ + "m.fs.F102.vap_outlet.temperature.fix(375)\n", + "m.fs.F102.deltaP.fix(-200000)" + ], + "outputs": [], + "execution_count": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the purge split fraction to 20% and the outlet pressure of the compressor is set to 350000 Pa. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.491620Z", + "start_time": "2025-11-20T21:46:10.485173Z" + } + }, + "source": [ + "m.fs.S101.split_fraction[0, \"purge\"].fix(0.2)\n", + "m.fs.C101.outlet.pressure.fix(350000)" + ], + "outputs": [], + "execution_count": 36 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "We have now defined all the feed conditions and the inputs required for the unit models. The system should now have 0 degrees of freedom i.e. should be a square problem. Please check that the degrees of freedom is 0. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.503512Z", + "start_time": "2025-11-20T21:46:10.495838Z" + } + }, + "source": [ + "# Todo: print the degrees of freedom" + ], + "outputs": [], + "execution_count": 37 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.535421Z", + "start_time": "2025-11-20T21:46:10.507798Z" + } + }, + "source": [ + "print(degrees_of_freedom(m))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n" + ] + } + ], + "execution_count": 38 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 Initializing the Model\n", + "\n", + "\n", + "\n", + "When a flowsheet contains a recycle loop, the outlet of a downstream unit becomes the inlet of an upstream unit, creating a cyclic dependency that prevents straightforward calculation of all stream conditions. The tear‐stream method is necessary because it “breaks” this loop: you select one recycle stream as the tear, assign it an initial guess, and then solve the rest of the flowsheet as if it were acyclic. Once the downstream units compute their outputs, you compare the calculated value of the torn stream to your initial guess and iteratively adjust until they coincide. Without tearing, the solver cannot establish a proper topological sequence or drive the recycle to convergence, making initialization—and ultimately steady‐state convergence—impossible.\n", + "\n", + "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", + "\n", + "\n", + "![](HDA_flowsheet.png)\n", + "\n", + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", + "\n", + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.578789Z", + "start_time": "2025-11-20T21:46:10.574025Z" + } + }, + "source": [ + "seq = SequentialDecomposition()\n", + "seq.options.select_tear_method = \"heuristic\"\n", + "seq.options.tear_method = \"Wegstein\"\n", + "seq.options.iterLim = 3\n", + "\n", + "# Using the SD tool\n", + "G = seq.create_graph(m)\n", + "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + "order = seq.calculation_order(G)" + ], + "outputs": [], + "execution_count": 40 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Which is the tear stream? Display tear set and order" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.588985Z", + "start_time": "2025-11-20T21:46:10.581810Z" + } + }, + "source": [ + "for o in heuristic_tear_set:\n", + " print(o.name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.s03\n" + ] + } + ], + "execution_count": 41 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " + ] + }, + { + "cell_type": "code", + "metadata": { + "scrolled": true, + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.602315Z", + "start_time": "2025-11-20T21:46:10.599259Z" + } + }, + "source": [ + "for o in order:\n", + " print(o[0].name)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs.I101\n", + "fs.R101\n", + "fs.F101\n", + "fs.S101\n", + "fs.C101\n", + "fs.M101\n" + ] + } + ], + "execution_count": 42 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", + "\n", + "![](HDA_tear_stream.png) \n", + "\n", + "\n", + "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.620357Z", + "start_time": "2025-11-20T21:46:10.617116Z" + } + }, + "source": [ + "tear_guesses = {\n", + " \"flow_mol_phase\": {\n", + " (0, \"Liq\"): F_liq_I101,\n", + " (0, \"Vap\"): F_vap_I102,\n", + " },\n", + " \"mole_frac_phase_comp\": {\n", + " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + " },\n", + " \"temperature\": {0: 303},\n", + " \"pressure\": {0: 350000},\n", + "}\n", + "\n", + "# Pass the tear_guess to the SD tool\n", + "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" + ], + "outputs": [], + "execution_count": 43 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:10.638254Z", + "start_time": "2025-11-20T21:46:10.635136Z" + } + }, + "source": [ + "def function(unit):\n", + " try:\n", + " initializer = unit.default_initializer()\n", + " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " except InitializationError:\n", + " solver = get_solver()\n", + " solver.solve(unit)" + ], + "outputs": [], + "execution_count": 44 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.022425Z", + "start_time": "2025-11-20T21:46:10.648251Z" + } + }, + "source": "seq.run(m, function)", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", + "WARNING: Wegstein failed to converge in 3 iterations\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", + "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", + "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" + ] + } + ], + "execution_count": 45 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets first import a helper function that will help us manually propagate and step through the flowsheet" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.069766Z", + "start_time": "2025-11-20T21:46:17.066725Z" + } + }, + "source": [ + "from idaes.core.util.initialization import propagate_state" + ], + "outputs": [], + "execution_count": 46 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", + "\n", + "We will first ensure that are current degrees of freedom is still zero" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.080343Z", + "start_time": "2025-11-20T21:46:17.077382Z" + } + }, + "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", + "outputs": [], + "execution_count": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.093180Z", + "start_time": "2025-11-20T21:46:17.089671Z" + } + }, + "source": [ + "# m.fs.s03_expanded.deactivate()\n", + "#\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + ], + "outputs": [], + "execution_count": 48 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.105510Z", + "start_time": "2025-11-20T21:46:17.099824Z" + } + }, + "source": [ + "# tear_guesses = {\n", + "# \"flow_mol_phase\": {\n", + "# (0, \"Liq\"): F_liq_I101,\n", + "# (0, \"Vap\"): F_vap_I102,\n", + "#\n", + "# },\n", + "# \"mole_frac_phase_comp\": {\n", + "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", + "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", + "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", + "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", + "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", + "# },\n", + "# \"temperature\": {0: 303},\n", + "# \"pressure\": {0: 350000},\n", + "# }\n", + "#\n", + "# for k, v in tear_guesses.items():\n", + "# for k1, v1 in v.items():\n", + "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "#\n", + "# DOF_initial = degrees_of_freedom(m)\n", + "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" + ], + "outputs": [], + "execution_count": 49 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.117110Z", + "start_time": "2025-11-20T21:46:17.113630Z" + } + }, + "source": [ + "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", + "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + "#\n", + "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", + "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + "#\n", + "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", + "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + "#\n", + "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", + "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + "#\n", + "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", + "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + "#\n", + "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", + "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + "#\n", + "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", + "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + "#\n", + "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", + "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + "#\n", + "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", + "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" + ], + "outputs": [], + "execution_count": 50 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.226222Z", + "start_time": "2025-11-20T21:46:17.129942Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + "}\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=300\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", + " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", + " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", + " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", + " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", + " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 6\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", + "\n", + "\n", + "Number of objective function evaluations = 7\n", + "Number of objective gradient evaluations = 7\n", + "Number of equality constraint evaluations = 7\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 7\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 6\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", + "Total CPU secs in NLP function evaluations = 0.001\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 51 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.258332Z", + "start_time": "2025-11-20T21:46:17.233298Z" + } + }, + "source": [ + "for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + "m.fs.s03_expanded.activate()\n", + "print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The DOF is 0 after unfixing the values and reactivating the tear stream\n" + ] + } + ], + "execution_count": 52 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6 Solving the Model" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.268422Z", + "start_time": "2025-11-20T21:46:17.265316Z" + } + }, + "source": [ + "optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + "}" + ], + "outputs": [], + "execution_count": 53 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following:\n", + "\n", + "solver = get_solver(solver_options=optarg)
\n", + "results = solver.solve(m, tee=True)\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code.\n", + "
\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.285774Z", + "start_time": "2025-11-20T21:46:17.281657Z" + } + }, + "source": [ + "# Create the solver object\n", + "\n", + "# Solve the model" + ], + "outputs": [], + "execution_count": 54 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.382669Z", + "start_time": "2025-11-20T21:46:17.293013Z" + } + }, + "source": [ + "# Create the solver object\n", + "solver = get_solver(\"ipopt_v2\", options=optarg)\n", + "\n", + "# Solve the model\n", + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 920\n", + "Number of nonzeros in inequality constraint Jacobian.: 0\n", + "Number of nonzeros in Lagrangian Hessian.............: 456\n", + "\n", + "Total number of variables............................: 218\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 147\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 218\n", + "Total number of inequality constraints...............: 0\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (10193)\n", + " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", + " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", + " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", + " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 4\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 5\n", + "Number of objective gradient evaluations = 5\n", + "Number of equality constraint evaluations = 5\n", + "Number of inequality constraint evaluations = 0\n", + "Number of equality constraint Jacobian evaluations = 5\n", + "Number of inequality constraint Jacobian evaluations = 0\n", + "Number of Lagrangian Hessian evaluations = 4\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", + "Total CPU secs in NLP function evaluations = 0.000\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 55 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7 Analyze the results\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window.\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "noauto" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.403453Z", + "start_time": "2025-11-20T21:46:17.400372Z" + } + }, + "source": [ + "# m.fs.visualize(\"HDA-Flowsheet\")" + ], + "outputs": [], + "execution_count": 57 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.448969Z", + "start_time": "2025-11-20T21:46:17.421434Z" + } + }, + "source": [ + "m.fs.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Flowsheet : fs Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", + " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", + " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", + " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", + " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", + " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + "====================================================================================\n" + ] + } + ], + "execution_count": 58 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the total operating cost?" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.475550Z", + "start_time": "2025-11-20T21:46:17.472001Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 424513.9640158265\n" + ] + } + ], + "execution_count": 59 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.596910Z", + "start_time": "2025-11-20T21:46:17.580529Z" + } + }, + "source": [ + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.26712 - - \n", + " Total Mole Fraction benzene dimensionless 0.76595 - - \n", + " Total Mole Fraction toluene dimensionless 0.23405 - - \n", + " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Temperature kelvin 325.00 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", + " flow_mol_phase Vap mole / second - 0.17224 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.66001 0.66001 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " temperature kelvin - 375.00 375.00 \n", + " pressure pascal - 1.5000e+05 1.5000e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8242963521555956\n" + ] + } + ], + "execution_count": 61 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101." + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.648524Z", + "start_time": "2025-11-20T21:46:17.638446Z" + } + }, + "source": [ + "from idaes.core.util.tables import (\n", + " create_stream_table_dataframe,\n", + " stream_table_dataframe_to_string,\n", + ")\n", + "\n", + "st = create_stream_table_dataframe({\"Reactor\": m.fs.s05, \"Light Gases\": m.fs.s06})\n", + "print(stream_table_dataframe_to_string(st))" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Units Reactor Light Gases\n", + "Total Molar Flowrate mole / second 2.0320 1.7648 \n", + "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 822.07 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" + ] + } + ], + "execution_count": 63 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8 Optimization\n", + "\n", + "\n", + "We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\\%. However, we are losing around 42\\% of benzene in F101 vapor outlet stream. \n", + "\n", + "Let us try to minimize this cost such that:\n", + "- we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream\n", + "- purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80%\n", + "- restricting the benzene loss in F101 vapor outlet to less than 20%\n", + "\n", + "For this problem, our decision variables are as follows:\n", + "- H101 outlet temperature\n", + "- R101 cooling duty provided\n", + "- F101 outlet temperature\n", + "- F102 outlet temperature\n", + "- F102 deltaP in the flash tank\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us declare our objective function for this problem. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.675626Z", + "start_time": "2025-11-20T21:46:17.671136Z" + } + }, + "source": [ + "m.fs.objective = Objective(expr=m.fs.operating_cost)" + ], + "outputs": [], + "execution_count": 64 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.691883Z", + "start_time": "2025-11-20T21:46:17.687385Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature.unfix()\n", + "m.fs.R101.heat_duty.unfix()\n", + "m.fs.F101.vap_outlet.temperature.unfix()\n", + "m.fs.F102.vap_outlet.temperature.unfix()" + ], + "outputs": [], + "execution_count": 65 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.707409Z", + "start_time": "2025-11-20T21:46:17.704141Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102" + ], + "outputs": [], + "execution_count": 66 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.720592Z", + "start_time": "2025-11-20T21:46:17.717532Z" + } + }, + "source": [ + "# Todo: Unfix deltaP for F102\n", + "m.fs.F102.deltaP.unfix()" + ], + "outputs": [], + "execution_count": 67 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we need to set bounds on these decision variables to values shown below:\n", + "\n", + " - H101 outlet temperature [500, 600] K\n", + " - R101 outlet temperature [600, 800] K\n", + " - F101 outlet temperature [298, 450] K\n", + " - F102 outlet temperature [298, 450] K\n", + " - F102 outlet pressure [105000, 110000] Pa\n", + "\n", + "Let us first set the variable bound for the H101 outlet temperature as shown below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.779305Z", + "start_time": "2025-11-20T21:46:17.775669Z" + } + }, + "source": [ + "m.fs.H101.outlet.temperature[0].setlb(500)\n", + "m.fs.H101.outlet.temperature[0].setub(600)" + ], + "outputs": [], + "execution_count": 69 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, set the variable bound for the R101 outlet temperature.\n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.797044Z", + "start_time": "2025-11-20T21:46:17.794614Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature" + ], + "outputs": [], + "execution_count": 70 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.812504Z", + "start_time": "2025-11-20T21:46:17.807564Z" + } + }, + "source": [ + "# Todo: Set the bounds for reactor outlet temperature\n", + "m.fs.R101.outlet.temperature[0].setlb(600)\n", + "m.fs.R101.outlet.temperature[0].setub(800)" + ], + "outputs": [], + "execution_count": 71 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us fix the bounds for the rest of the decision variables. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.827227Z", + "start_time": "2025-11-20T21:46:17.822681Z" + } + }, + "source": [ + "m.fs.F101.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F101.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setlb(298.0)\n", + "m.fs.F102.vap_outlet.temperature[0].setub(450.0)\n", + "m.fs.F102.vap_outlet.pressure[0].setlb(105000)\n", + "m.fs.F102.vap_outlet.pressure[0].setub(110000)" + ], + "outputs": [], + "execution_count": 72 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \\% of the benzene available in the reactor outlet. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.848212Z", + "start_time": "2025-11-20T21:46:17.844101Z" + } + }, + "source": [ + "m.fs.overhead_loss = Constraint(\n", + " expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " <= 0.20\n", + " * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[\"Vap\", \"benzene\"]\n", + ")" + ], + "outputs": [], + "execution_count": 73 + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [ + "exercise" + ] + }, + "source": [ + "
\n", + "Inline Exercise:\n", + "Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. \n", + "\n", + "Use Shift+Enter to run the cell once you have typed in your code. \n", + "
" + ] + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "exercise" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.862411Z", + "start_time": "2025-11-20T21:46:17.859385Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint" + ], + "outputs": [], + "execution_count": 74 + }, + { + "cell_type": "code", + "metadata": { + "tags": [ + "solution" + ], + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.876414Z", + "start_time": "2025-11-20T21:46:17.872250Z" + } + }, + "source": [ + "# Todo: Add minimum product flow constraint\n", + "m.fs.product_flow = Constraint(\n", + " expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[\n", + " \"Vap\", \"benzene\"\n", + " ]\n", + " >= 0.15\n", + ")" + ], + "outputs": [], + "execution_count": 75 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. " + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:17.890250Z", + "start_time": "2025-11-20T21:46:17.887141Z" + } + }, + "source": [ + "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" + ], + "outputs": [], + "execution_count": 76 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "We have now defined the optimization problem and we are now ready to solve this problem. \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.024828Z", + "start_time": "2025-11-20T21:46:17.897344Z" + } + }, + "source": [ + "results = solver.solve(m, tee=True)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ipopt 3.13.2: linear_solver=\"ma57\"\n", + "max_iter=1000\n", + "nlp_scaling_method=\"user-scaling\"\n", + "tol=1e-08\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", + "\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", + "\n", + "\n", + "******************************************************************************\n", + "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", + " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", + " For more information visit http://projects.coin-or.org/Ipopt\n", + "\n", + "This version of Ipopt was compiled from source code available at\n", + " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", + " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", + " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", + "\n", + "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", + " for large-scale scientific computation. All technical papers, sales and\n", + " publicity material resulting from use of the HSL codes within IPOPT must\n", + " contain the following acknowledgement:\n", + " HSL, a collection of Fortran codes for large-scale scientific\n", + " computation. See http://www.hsl.rl.ac.uk.\n", + "******************************************************************************\n", + "\n", + "This is Ipopt version 3.13.2, running with linear solver ma57.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 938\n", + "Number of nonzeros in inequality constraint Jacobian.: 9\n", + "Number of nonzeros in Lagrangian Hessian.............: 504\n", + "\n", + "Reallocating memory for MA57: lfact (10594)\n", + "Total number of variables............................: 224\n", + " variables with only lower bounds: 56\n", + " variables with lower and upper bounds: 151\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 219\n", + "Total number of inequality constraints...............: 3\n", + " inequality constraints with only lower bounds: 2\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 1\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "Reallocating memory for MA57: lfact (11249)\n", + " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", + " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", + " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", + " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", + " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", + " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", + " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", + " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", + " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", + " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", + " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", + " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", + " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", + " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", + " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", + " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", + " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", + " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", + " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", + " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", + " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", + " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", + " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", + " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", + " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", + " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", + "\n", + "Number of Iterations....: 28\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", + "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", + "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", + "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", + "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", + "\n", + "\n", + "Number of objective function evaluations = 35\n", + "Number of objective gradient evaluations = 29\n", + "Number of equality constraint evaluations = 35\n", + "Number of inequality constraint evaluations = 35\n", + "Number of equality constraint Jacobian evaluations = 29\n", + "Number of inequality constraint Jacobian evaluations = 29\n", + "Number of Lagrangian Hessian evaluations = 28\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", + "Total CPU secs in NLP function evaluations = 0.006\n", + "\n", + "EXIT: Optimal Solution Found.\n" + ] + } + ], + "execution_count": 77 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 8.1 Optimization Results\n", + "\n", + "Display the results and product specifications" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.074231Z", + "start_time": "2025-11-20T21:46:18.053675Z" + } + }, + "source": [ + "print(\"operating cost = $\", value(m.fs.operating_cost))\n", + "\n", + "print()\n", + "print(\"Product flow rate and purity in F102\")\n", + "\n", + "m.fs.F102.report()\n", + "\n", + "print()\n", + "print(\"benzene purity = \", value(m.fs.purity))\n", + "\n", + "print()\n", + "print(\"Overhead loss in F101\")\n", + "m.fs.F101.report()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operating cost = $ 318024.90940142004\n", + "\n", + "Product flow rate and purity in F102\n", + "\n", + "====================================================================================\n", + "Unit : fs.F102 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 0.28812 - - \n", + " Total Mole Fraction benzene dimensionless 0.75463 - - \n", + " Total Mole Fraction toluene dimensionless 0.24537 - - \n", + " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", + " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Temperature kelvin 301.88 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", + " flow_mol_phase Vap mole / second - 0.18319 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.64256 0.64256 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.35744 0.35744 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.81883 0.81883 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.18117 0.18117 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.1799e-08 1.1799e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.0825e-08 4.0825e-08 \n", + " temperature kelvin - 362.93 362.93 \n", + " pressure pascal - 1.0500e+05 1.0500e+05 \n", + "====================================================================================\n", + "\n", + "benzene purity = 0.8188295888411846\n", + "\n", + "Overhead loss in F101\n", + "\n", + "====================================================================================\n", + "Unit : fs.F101 Time: 0.0\n", + "------------------------------------------------------------------------------------\n", + " Unit Performance\n", + "\n", + " Variables: \n", + "\n", + " Key : Value : Units : Fixed : Bounds\n", + " Heat Duty : -66423. : watt : False : (None, None)\n", + " Pressure Change : 0.0000 : pascal : True : (None, None)\n", + "\n", + "------------------------------------------------------------------------------------\n", + " Stream Table\n", + " Units Inlet Vapor Outlet Liquid Outlet\n", + " Total Molar Flowrate mole / second 1.9480 - - \n", + " Total Mole Fraction benzene dimensionless 0.13952 - - \n", + " Total Mole Fraction toluene dimensionless 0.039059 - - \n", + " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", + " Total Mole Fraction methane dimensionless 0.63725 - - \n", + " Temperature kelvin 763.51 - - \n", + " Pressure pascal 3.5000e+05 - - \n", + " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", + " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", + " mole_frac_phase_comp ('Liq', 'benzene') dimensionless - 0.75463 0.75463 \n", + " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.24537 0.24537 \n", + " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.032748 0.032748 \n", + " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.0032478 0.0032478 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 0.21614 0.21614 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 0.74786 0.74786 \n", + " temperature kelvin - 301.88 301.88 \n", + " pressure pascal - 3.5000e+05 3.5000e+05 \n", + "====================================================================================\n" + ] + } + ], + "execution_count": 79 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display optimal values for the decision variables" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-20T21:46:18.106001Z", + "start_time": "2025-11-20T21:46:18.101768Z" + } + }, + "source": [ + "print(\n", + " f\"\"\"Optimal Values:\n", + "\n", + "H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K\n", + "\n", + "R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K\n", + "\n", + "F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K\n", + "\n", + "F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K\n", + "F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa\n", + "\"\"\"\n", + ")" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimal Values:\n", + "\n", + "H101 outlet temperature = 500.000 K\n", + "\n", + "R101 outlet temperature = 763.507 K\n", + "\n", + "F101 outlet temperature = 301.881 K\n", + "\n", + "F102 outlet temperature = 362.935 K\n", + "F102 outlet pressure = 105000.000 Pa\n", + "\n" + ] + } + ], + "execution_count": 81 + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 3 } \ No newline at end of file diff --git a/idaes_examples/notebooks/docs/tut/core/initializing_testing.py b/idaes_examples/notebooks/docs/tut/core/initializing_testing.py new file mode 100644 index 00000000..673ccac9 --- /dev/null +++ b/idaes_examples/notebooks/docs/tut/core/initializing_testing.py @@ -0,0 +1,107 @@ +# Import required packages +from idaes.models_extra.power_generation.properties.natural_gas_PR import get_prop +from pyomo.environ import ( + ConcreteModel, + SolverFactory, + value, + units, + TransformationFactory, + Expression, +) +from idaes.core import FlowsheetBlock +from idaes.core.util.initialization import propagate_state +import idaes.logger as idaeslog +from idaes.models.properties import iapws95 +from idaes.models.unit_models import Feed +from idaes.models.unit_models.heater import Heater +from idaes.models.unit_models.heat_exchanger import ( + HeatExchanger, + delta_temperature_amtd_callback, +) +from pyomo.network import Arc, SequentialDecomposition +from idaes.core.util.model_statistics import degrees_of_freedom + +# Create the ConcreteModel and the FlowsheetBlock, and attach the flowsheet block to it. +m = ConcreteModel() + +m.fs = FlowsheetBlock(dynamic=False) + +m.fs.properties = iapws95.Iapws95ParameterBlock() + +m.fs.feed = Feed(property_package=m.fs.properties) +m.fs.heater = Heater(property_package=m.fs.properties) +m.fs.heat_exchanger = HeatExchanger( + delta_temperature_callback=delta_temperature_amtd_callback, + hot_side_name="shell", + cold_side_name="tube", + shell={"property_package": m.fs.properties}, + tube={"property_package": m.fs.properties}, +) + +m.fs.s01 = Arc(source=m.fs.feed.outlet, destination=m.fs.heat_exchanger.cold_side_inlet) +m.fs.s02 = Arc( + source=m.fs.heat_exchanger.cold_side_outlet, destination=m.fs.heater.inlet +) +m.fs.s03 = Arc( + source=m.fs.heater.outlet, destination=m.fs.heat_exchanger.hot_side_inlet +) + +TransformationFactory("network.expand_arcs").apply_to(m) +DOF_initial = degrees_of_freedom(m) +print("The initial DOF is {0}".format(DOF_initial)) + +# Fix the stream inlet conditions +m.fs.feed.flow_mol[0].fix(100) # mol/s +m.fs.feed.pressure[0].fix(101325) # Pa +m.fs.feed.enth_mol[0].fix(value(iapws95.htpx(T=293 * units.K, P=101325 * units.Pa))) + + +m.fs.heat_exchanger.overall_heat_transfer_coefficient[0].fix(500) # W/m2/K +m.fs.heat_exchanger.area.fix(50) + + +m.fs.heater.outlet.enth_mol.fix( + value(iapws95.htpx(T=1073 * units.K, P=101325 * units.Pa)) +) + +DOF_initial = degrees_of_freedom(m) +print("The DOF is {0}".format(DOF_initial)) + +# Provide initial guess for the shell inlet and create tear stream +m.fs.heat_exchanger.shell_inlet.flow_mol.fix(100) # mol/s +m.fs.heat_exchanger.shell_inlet.enth_mol[0].fix( + value(iapws95.htpx(T=1073 * units.K, P=101325 * 1.5 * units.Pa)) +) +m.fs.heat_exchanger.shell_inlet.pressure[0].fix(101325) # Pa +m.fs.s03_expanded.deactivate() + +DOF_initial = degrees_of_freedom(m) +print("The DOF is {0} after creating tear stream".format(DOF_initial)) + +m.fs.report() + +m.fs.feed.initialize(outlvl=idaeslog.INFO) +propagate_state(m.fs.s01) +m.fs.report() +m.fs.heat_exchanger.initialize(outlvl=idaeslog.INFO) +propagate_state(m.fs.s02) +m.fs.report() +m.fs.heater.initialize(outlvl=idaeslog.INFO) + +m.fs.report() + +# Solve the model +from idaes.core.solvers import get_solver + +solver = get_solver() +results = solver.solve(m, tee=False) + +# Reactivate tear stream, and unfix shell side initial conditions +m.fs.heat_exchanger.shell_inlet.flow_mol.unfix() +m.fs.heat_exchanger.shell_inlet.enth_mol[0].unfix() +m.fs.heat_exchanger.shell_inlet.pressure[0].unfix() +m.fs.s03_expanded.activate() + +results = solver.solve(m, tee=False) + +m.fs.report() From fc5e1c5c955db230efffbdfcfd1829c4282acb6a Mon Sep 17 00:00:00 2001 From: Tanner Polley Date: Mon, 12 Jan 2026 17:14:12 -0700 Subject: [PATCH 36/36] Revised and fixed the HDA tutorial to work with updated FpTPxpc state definition and initialization methods --- .../mod/hda/hda_flowsheet_extras.py | 200 ++ .../mod/hda/hda_ideal_VLE_modular.py | 51 +- .../docs/tut/core/hda_flowsheet.ipynb | 2052 ++++++----------- .../notebooks/docs/tut/core/hda_flowsheet.py | 757 ++---- 4 files changed, 1079 insertions(+), 1981 deletions(-) create mode 100644 idaes_examples/mod/hda/hda_flowsheet_extras.py diff --git a/idaes_examples/mod/hda/hda_flowsheet_extras.py b/idaes_examples/mod/hda/hda_flowsheet_extras.py new file mode 100644 index 00000000..8a716ffa --- /dev/null +++ b/idaes_examples/mod/hda/hda_flowsheet_extras.py @@ -0,0 +1,200 @@ +import numpy as np +from idaes.core.util.model_statistics import degrees_of_freedom +from idaes.core.solvers import get_solver +import idaes.logger as idaeslog + +def FpcTP_to_FpTPxpc(flow_mol_phase_comp): + + flow_mol_phase = { + "Vap": 0, + "Liq": 0, + } + mole_frac_phase_comp = {} + + for (p, c) in flow_mol_phase_comp.keys(): + flow_mol_phase[p] += flow_mol_phase_comp[(p, c)] + for (p, c) in flow_mol_phase_comp.keys(): + if flow_mol_phase[p] == 0.0: + mole_frac_phase_comp[p, c] = 0.0 + else: + mole_frac_phase_comp[p, c] = flow_mol_phase_comp[(p, c)] / flow_mol_phase[p] + + return flow_mol_phase, mole_frac_phase_comp + + +def fix_inlet_states(m): + + eps = 1e-5 + flow_mol_phase_comp_101 = { + ("Vap", "benzene"): eps, + ("Vap", "toluene"): eps, + ("Vap", "hydrogen"): eps, + ("Vap", "methane"): eps, + ("Liq", "benzene"): eps, + ("Liq", "toluene"): 0.30, + } + + flow_mol_phase_101, mole_frac_phase_comp_101 = FpcTP_to_FpTPxpc(flow_mol_phase_comp_101) + + m.fs.I101.flow_mol_phase[0, "Vap"].fix(flow_mol_phase_101["Vap"]) + m.fs.I101.flow_mol_phase[0, "Liq"].fix(flow_mol_phase_101["Liq"]) + m.fs.I101.mole_frac_phase_comp[0, "Vap", "benzene"].fix(mole_frac_phase_comp_101["Vap", "benzene"]) + m.fs.I101.mole_frac_phase_comp[0, "Vap", "toluene"].fix(mole_frac_phase_comp_101["Vap", "toluene"]) + m.fs.I101.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(mole_frac_phase_comp_101["Vap", "hydrogen"]) + m.fs.I101.mole_frac_phase_comp[0, "Vap", "methane"].fix(mole_frac_phase_comp_101["Vap", "methane"]) + m.fs.I101.mole_frac_phase_comp[0, "Liq", "benzene"].fix(mole_frac_phase_comp_101["Liq", "benzene"]) + m.fs.I101.mole_frac_phase_comp[0, "Liq", "toluene"].fix(mole_frac_phase_comp_101["Liq", "toluene"]) + m.fs.I101.temperature.fix(303.2) + m.fs.I101.pressure.fix(350000) + + flow_mol_phase_comp_102 = { + ("Vap", "benzene"): eps, + ("Vap", "toluene"): eps, + ("Vap", "hydrogen"): .30, + ("Vap", "methane"): .02, + ("Liq", "benzene"): eps, + ("Liq", "toluene"): eps, + } + + flow_mol_phase_102, mole_frac_phase_comp_102 = FpcTP_to_FpTPxpc(flow_mol_phase_comp_102) + + m.fs.I102.flow_mol_phase[0, "Vap"].fix(flow_mol_phase_102["Vap"]) + m.fs.I102.flow_mol_phase[0, "Liq"].fix(flow_mol_phase_102["Liq"]) + m.fs.I102.mole_frac_phase_comp[0, "Vap", "benzene"].fix(mole_frac_phase_comp_102["Vap", "benzene"]) + m.fs.I102.mole_frac_phase_comp[0, "Vap", "toluene"].fix(mole_frac_phase_comp_102["Vap", "toluene"]) + m.fs.I102.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(mole_frac_phase_comp_102["Vap", "hydrogen"]) + m.fs.I102.mole_frac_phase_comp[0, "Vap", "methane"].fix(mole_frac_phase_comp_102["Vap", "methane"]) + m.fs.I102.mole_frac_phase_comp[0, "Liq", "benzene"].fix(mole_frac_phase_comp_102["Liq", "benzene"]) + m.fs.I102.mole_frac_phase_comp[0, "Liq", "toluene"].fix(mole_frac_phase_comp_102["Liq", "toluene"]) + m.fs.I102.temperature.fix(303.2) + m.fs.I102.pressure.fix(350000) + + tear_guesses = { + "flow_mol_phase": { + (0, "Liq"): flow_mol_phase_101["Liq"], + (0, "Vap"): flow_mol_phase_102["Vap"], + }, + "mole_frac_phase_comp": { + (0, "Liq", "benzene"): mole_frac_phase_comp_101["Liq", "benzene"], + (0, "Liq", "toluene"): mole_frac_phase_comp_101["Liq", "toluene"], + (0, "Vap", "benzene"): mole_frac_phase_comp_102["Vap", "benzene"], + (0, "Vap", "toluene"): mole_frac_phase_comp_102["Vap", "toluene"], + (0, "Vap", "methane"): mole_frac_phase_comp_102["Vap", "hydrogen"], + (0, "Vap", "hydrogen"): mole_frac_phase_comp_102["Vap", "methane"], + }, + "temperature": {0: 303}, + "pressure": {0: 350000}, + } + + return tear_guesses + + +def initialize_unit(unit): + from idaes.core.util.exceptions import InitializationError + import idaes.logger as idaeslog + + optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 1000, + "tol": 1e-8, + } + + try: + initializer = unit.default_initializer(solver_options=optarg) + initializer.initialize(unit, output_level=idaeslog.INFO_LOW) + except InitializationError: + solver = get_solver(solver_options=optarg) + solver.solve(unit) + + +def manual_propagation(m, tear_guesses): + from idaes.core.util.initialization import propagate_state + + print(f"The DOF is {degrees_of_freedom(m)} initially") + m.fs.s03_expanded.deactivate() + print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") + + for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.s03.destination, k)[k1].fix(v1) + + DOF_initial = degrees_of_freedom(m) + + print(f"The DOF is {degrees_of_freedom(m)} after setting the tear stream") + + optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 300, + # "tol": 1e-10, + } + + solver = get_solver(solver_options=optarg) + + initialize_unit(m.fs.H101) # Initialize Heater + propagate_state(m.fs.s04) # Establish connection between Heater and Reactor + initialize_unit(m.fs.R101) # Initialize Reactor + propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit + initialize_unit(m.fs.F101) # Initialize First Flash Unit + propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter + propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit + initialize_unit(m.fs.S101) # Initialize Splitter + propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor + initialize_unit(m.fs.C101) # Initialize Compressor + propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer + initialize_unit(m.fs.I101) # Initialize Toluene Inlet + propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer + initialize_unit(m.fs.I102) # Initialize Hydrogen Inlet + propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer + initialize_unit(m.fs.M101) # Initialize Mixer + propagate_state(m.fs.s03) # Establish connection between Mixer and Heater + solver.solve(m.fs.F102) + propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product + propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product + propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product + + optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 300, + "tol": 1e-8, + } + solver = get_solver("ipopt_v2", options=optarg) + solver.solve(m, tee=False) + + for k, v in tear_guesses.items(): + for k1, v1 in v.items(): + getattr(m.fs.H101.inlet, k)[k1].unfix() + + m.fs.s03_expanded.activate() + print( + f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" + ) + + +def automatic_propagation(m, tear_guesses): + + from pyomo.network import SequentialDecomposition + + seq = SequentialDecomposition() + seq.options.select_tear_method = "heuristic" + seq.options.tear_method = "Wegstein" + seq.options.iterLim = 5 + + # Using the SD tool + G = seq.create_graph(m) + heuristic_tear_set = seq.tear_set_arcs(G, method="heuristic") + order = seq.calculation_order(G) + + # Pass the tear_guess to the SD tool + seq.set_guesses_for(heuristic_tear_set[0].destination, tear_guesses) + + print(f'Tear Stream starts at: {heuristic_tear_set[0].destination.name}') + + for o in order: + print(o[0].name) + + seq.run(m, initialize_unit) + + diff --git a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py index 13ffff4a..7b225b65 100644 --- a/idaes_examples/mod/hda/hda_ideal_VLE_modular.py +++ b/idaes_examples/mod/hda/hda_ideal_VLE_modular.py @@ -32,6 +32,7 @@ from idaes.core.util.constants import Constants from idaes.models.properties.modular_properties.state_definitions.FpTPxpc import FpTPxpc +from idaes.models.properties.modular_properties.state_definitions.FpcTP import FpcTP from idaes.models.properties.modular_properties.eos.ideal import Ideal from idaes.models.properties.modular_properties.phase_equil import SmoothVLE from idaes.models.properties.modular_properties.phase_equil.bubble_dew import ( @@ -159,8 +160,8 @@ def return_expression(b, cobj, T): "4": (0, pyunits.J / pyunits.kmol / pyunits.K**4), "5": (0, pyunits.J / pyunits.kmol / pyunits.K**5), }, - "enth_mol_form_liq_comp_ref": (49.0e3, pyunits.J / pyunits.mol), # [3] - "enth_mol_form_vap_comp_ref": (82.9e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (3.387e4, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (4.202, pyunits.dimensionless), # [1] "B": (1322, pyunits.K), @@ -197,8 +198,8 @@ def return_expression(b, cobj, T): "4": (0, pyunits.J / pyunits.kmol / pyunits.K**4), "5": (0, pyunits.J / pyunits.kmol / pyunits.K**5), }, - "enth_mol_form_liq_comp_ref": (12.0e3, pyunits.J / pyunits.mol), # [3] - "enth_mol_form_vap_comp_ref": (50.1e3, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] + "enth_mol_form_vap_comp_ref": (3.8262e4, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (4.216, pyunits.dimensionless), # [1] "B": (1435, pyunits.K), @@ -216,25 +217,10 @@ def return_expression(b, cobj, T): "mw": (2.016e-3, pyunits.kg / pyunits.mol), # [1] "pressure_crit": (12.9e5, pyunits.Pa), # [1] "temperature_crit": (33.0, pyunits.K), # [1] - # "dens_mol_liq_comp_coeff": { - # "eqn_type": 1, - # "1": (5.414, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 - # "2": (0.34893, None), - # "3": (33.19, pyunits.K), - # "4": (0.2706, None), - # }, "cp_mol_ig_comp_coeff": { f"a{k}": (cp_ig_data["hydrogen", k], pyunits.K**-k) for k in range(5) }, - # "cp_mol_liq_comp_coeff": { - # "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] - # "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), - # "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), - # "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - # "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), - # }, - # "enth_mol_form_liq_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] "enth_mol_form_vap_comp_ref": (0.0, pyunits.J / pyunits.mol), # [3] "pressure_sat_comp_coeff": { "A": (3.543, pyunits.dimensionless), # [1] @@ -253,28 +239,8 @@ def return_expression(b, cobj, T): "mw": (16.043e-3, pyunits.kg / pyunits.mol), # [1] "pressure_crit": (4.599e6, pyunits.Pa), # [1] "temperature_crit": (190.564, pyunits.K), # [1] - # "dens_mol_liq_comp_coeff": { - # "eqn_type": 1, - # "1": (2.9214, pyunits.kmol * pyunits.m ** -3), # [2] pg. 2-98 - # "2": (0.28976, None), - # "3": (190.56, pyunits.K), - # "4": (0.28881, None), - # }, - "cp_mol_ig_comp_coeff": { - f"a{k}": (cp_ig_data["methane", k], pyunits.K**-k) for k in range(5) - }, - # "cp_mol_liq_comp_coeff": { - # "1": (0, pyunits.J / pyunits.kmol / pyunits.K), # [2] - # "2": (0, pyunits.J / pyunits.kmol / pyunits.K ** 2), - # "3": (0, pyunits.J / pyunits.kmol / pyunits.K ** 3), - # "4": (0, pyunits.J / pyunits.kmol / pyunits.K ** 4), - # "5": (0, pyunits.J / pyunits.kmol / pyunits.K ** 5), - # }, - # "enth_mol_form_liq_comp_ref": (-74.52e3, pyunits.J / pyunits.mol), # [3] - "enth_mol_form_vap_comp_ref": ( - -74.52e3, - pyunits.J / pyunits.mol, - ), # [3] + "cp_mol_ig_comp_coeff": {f"a{k}": (cp_ig_data["methane", k], pyunits.K**-k) for k in range(5)}, + "enth_mol_form_vap_comp_ref": (0.0, pyunits.J / pyunits.mol,), # [3] "pressure_sat_comp_coeff": { "A": (3.990, pyunits.dimensionless), # [1] "B": (443.0, pyunits.K), @@ -300,7 +266,7 @@ def return_expression(b, cobj, T): # # Specifying state definition "state_definition": FpTPxpc, "state_bounds": { - "flow_mol_phase": (1e-12, 0.5, 100, pyunits.mol / pyunits.s), + "flow_mol_phase": (0.0, 0.5, 100, pyunits.mol / pyunits.s), "temperature": (273.15, 298.15, 1500, pyunits.K), "pressure": (100000, 101325, 1000000, pyunits.Pa), }, @@ -318,3 +284,4 @@ def return_expression(b, cobj, T): thermo_config_vapor.pop("phases_in_equilibrium") thermo_config_vapor.pop("phase_equilibrium_state") thermo_config_vapor.pop("bubble_dew_method") + diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb index abfc2b04..4f4f6033 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.ipynb @@ -8,8 +8,8 @@ "hide-cell" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:04.904828Z", - "start_time": "2025-11-20T21:46:04.900352Z" + "end_time": "2026-01-13T00:12:27.028013200Z", + "start_time": "2026-01-13T00:12:27.015275700Z" } }, "source": [ @@ -38,7 +38,7 @@ "\n", "Author: Jaffer Ghouse
\n", "Maintainer: Tanner Polley
\n", - "Updated: 2025-11-19\n", + "Updated: 2026-1-12\n", "\n", "## Learning outcomes\n", "\n", @@ -121,8 +121,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:05.294578Z", - "start_time": "2025-11-20T21:46:04.908296Z" + "end_time": "2026-01-13T00:12:27.614407500Z", + "start_time": "2026-01-13T00:12:27.029098600Z" } }, "source": [ @@ -135,7 +135,7 @@ " TransformationFactory,\n", " value,\n", ")\n", - "from pyomo.network import Arc, SequentialDecomposition" + "from pyomo.network import Arc" ], "outputs": [], "execution_count": 2 @@ -159,13 +159,11 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:06.806301Z", - "start_time": "2025-11-20T21:46:05.297760Z" + "end_time": "2026-01-13T00:12:29.427113300Z", + "start_time": "2026-01-13T00:12:27.699286500Z" } }, - "source": [ - "from idaes.core import FlowsheetBlock" - ], + "source": "from idaes.core import FlowsheetBlock", "outputs": [], "execution_count": 3 }, @@ -173,8 +171,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:09.936732Z", - "start_time": "2025-11-20T21:46:09.883054Z" + "end_time": "2026-01-13T00:12:29.495404700Z", + "start_time": "2026-01-13T00:12:29.432738900Z" } }, "source": [ @@ -186,9 +184,7 @@ " StoichiometricReactor,\n", " Feed,\n", " Product,\n", - ")\n", - "from idaes.core.util.exceptions import InitializationError\n", - "import idaes.logger as idaeslog" + ")" ], "outputs": [], "execution_count": 4 @@ -210,8 +206,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:09.952476Z", - "start_time": "2025-11-20T21:46:09.949367Z" + "end_time": "2026-01-13T00:12:29.504917Z", + "start_time": "2026-01-13T00:12:29.497935600Z" } }, "source": [ @@ -227,8 +223,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:09.963041Z", - "start_time": "2025-11-20T21:46:09.957319Z" + "end_time": "2026-01-13T00:12:29.528819Z", + "start_time": "2026-01-13T00:12:29.505935Z" } }, "source": [ @@ -249,8 +245,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:09.976914Z", - "start_time": "2025-11-20T21:46:09.971944Z" + "end_time": "2026-01-13T00:12:29.539485800Z", + "start_time": "2026-01-13T00:12:29.531348400Z" } }, "source": [ @@ -284,8 +280,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.017098Z", - "start_time": "2025-11-20T21:46:09.981997Z" + "end_time": "2026-01-13T00:12:29.627980300Z", + "start_time": "2026-01-13T00:12:29.540486900Z" } }, "cell_type": "code", @@ -315,8 +311,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.031538Z", - "start_time": "2025-11-20T21:46:10.025904Z" + "end_time": "2026-01-13T00:12:29.638672500Z", + "start_time": "2026-01-13T00:12:29.630018Z" } }, "source": [ @@ -337,8 +333,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.066746Z", - "start_time": "2025-11-20T21:46:10.035131Z" + "end_time": "2026-01-13T00:12:29.669834600Z", + "start_time": "2026-01-13T00:12:29.638672500Z" } }, "source": [ @@ -363,13 +359,12 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.114600Z", - "start_time": "2025-11-20T21:46:10.071845Z" + "end_time": "2026-01-13T00:12:29.718708300Z", + "start_time": "2026-01-13T00:12:29.672813900Z" } }, "source": [ "m.fs.I101 = Feed(property_package=m.fs.thermo_params)\n", - "\n", "m.fs.I102 = Feed(property_package=m.fs.thermo_params)\n", "\n", "m.fs.M101 = Mixer(\n", @@ -414,8 +409,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.121709Z", - "start_time": "2025-11-20T21:46:10.119134Z" + "end_time": "2026-01-13T00:12:29.737260500Z", + "start_time": "2026-01-13T00:12:29.719754300Z" } }, "source": [ @@ -431,8 +426,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.145853Z", - "start_time": "2025-11-20T21:46:10.127921Z" + "end_time": "2026-01-13T00:12:29.761429600Z", + "start_time": "2026-01-13T00:12:29.739837200Z" } }, "source": [ @@ -464,8 +459,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.167357Z", - "start_time": "2025-11-20T21:46:10.149935Z" + "end_time": "2026-01-13T00:12:29.785139300Z", + "start_time": "2026-01-13T00:12:29.762955300Z" } }, "source": [ @@ -489,8 +484,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.211911Z", - "start_time": "2025-11-20T21:46:10.173255Z" + "end_time": "2026-01-13T00:12:29.827217600Z", + "start_time": "2026-01-13T00:12:29.787651900Z" } }, "source": [ @@ -527,15 +522,13 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.226989Z", - "start_time": "2025-11-20T21:46:10.216839Z" + "end_time": "2026-01-13T00:12:29.844845200Z", + "start_time": "2026-01-13T00:12:29.829763300Z" } }, "source": [ "m.fs.P101 = Product(property_package=m.fs.thermo_params)\n", - "\n", "m.fs.P102 = Product(property_package=m.fs.thermo_params)\n", - "\n", "m.fs.P103 = Product(property_package=m.fs.thermo_params)" ], "outputs": [], @@ -561,8 +554,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.235541Z", - "start_time": "2025-11-20T21:46:10.231058Z" + "end_time": "2026-01-13T00:12:29.855598100Z", + "start_time": "2026-01-13T00:12:29.847349400Z" } }, "source": [ @@ -594,8 +587,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.245319Z", - "start_time": "2025-11-20T21:46:10.239913Z" + "end_time": "2026-01-13T00:12:29.865134200Z", + "start_time": "2026-01-13T00:12:29.857100Z" } }, "source": [ @@ -611,8 +604,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.254153Z", - "start_time": "2025-11-20T21:46:10.248481Z" + "end_time": "2026-01-13T00:12:29.873064300Z", + "start_time": "2026-01-13T00:12:29.865134200Z" } }, "source": [ @@ -633,8 +626,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.264461Z", - "start_time": "2025-11-20T21:46:10.258555Z" + "end_time": "2026-01-13T00:12:29.882527100Z", + "start_time": "2026-01-13T00:12:29.874065200Z" } }, "source": [ @@ -658,8 +651,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.274505Z", - "start_time": "2025-11-20T21:46:10.268918Z" + "end_time": "2026-01-13T00:12:29.891441800Z", + "start_time": "2026-01-13T00:12:29.882527100Z" } }, "source": [ @@ -681,8 +674,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.303264Z", - "start_time": "2025-11-20T21:46:10.278714Z" + "end_time": "2026-01-13T00:12:29.916831200Z", + "start_time": "2026-01-13T00:12:29.891441800Z" } }, "source": [ @@ -713,8 +706,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.312336Z", - "start_time": "2025-11-20T21:46:10.309074Z" + "end_time": "2026-01-13T00:12:29.926950800Z", + "start_time": "2026-01-13T00:12:29.918895100Z" } }, "source": [ @@ -744,8 +737,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.323538Z", - "start_time": "2025-11-20T21:46:10.318119Z" + "end_time": "2026-01-13T00:12:29.937452200Z", + "start_time": "2026-01-13T00:12:29.928143Z" } }, "source": [ @@ -773,8 +766,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.336983Z", - "start_time": "2025-11-20T21:46:10.328380Z" + "end_time": "2026-01-13T00:12:29.945656300Z", + "start_time": "2026-01-13T00:12:29.938460700Z" } }, "source": [ @@ -796,8 +789,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.345607Z", - "start_time": "2025-11-20T21:46:10.341996Z" + "end_time": "2026-01-13T00:12:29.954918200Z", + "start_time": "2026-01-13T00:12:29.947160400Z" } }, "source": [ @@ -822,8 +815,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.376586Z", - "start_time": "2025-11-20T21:46:10.349694Z" + "end_time": "2026-01-13T00:12:29.987120200Z", + "start_time": "2026-01-13T00:12:29.954918200Z" } }, "source": [ @@ -847,8 +840,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.409008Z", - "start_time": "2025-11-20T21:46:10.382157Z" + "end_time": "2026-01-13T00:12:30.023856500Z", + "start_time": "2026-01-13T00:12:29.995698600Z" } }, "source": [ @@ -862,87 +855,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to help with convergence and initializing." + "We will now be fixing the toluene feed (`I101`) stream to the conditions shown in the flowsheet above. Please note\n", + "that though this is a pure toluene feed, the remaining components are still assigned a very small non-zero value to\n", + "help with convergence and initializing. We will be importing a function that will specify the inlet conditions for\n", + "this example." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.418520Z", - "start_time": "2025-11-20T21:46:10.414167Z" + "end_time": "2026-01-13T00:12:30.037749600Z", + "start_time": "2026-01-13T00:12:30.025896900Z" } }, "source": [ - "F_liq_toluene = 0.30\n", - "F_liq_non_zero = 1e-5\n", - "\n", - "F_vap_I101 = F_liq_non_zero * 4\n", - "F_liq_I101 = F_liq_toluene + F_liq_non_zero\n", + "from idaes_examples.mod.hda.hda_flowsheet_extras import fix_inlet_states\n", "\n", - "m.fs.I101.flow_mol_phase[0, \"Vap\"].fix(F_vap_I101)\n", - "m.fs.I101.flow_mol_phase[0, \"Liq\"].fix(F_liq_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_liq_non_zero / F_vap_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_liq_non_zero / F_vap_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_liq_non_zero / F_vap_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_liq_non_zero / F_vap_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I101)\n", - "m.fs.I101.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_toluene / F_liq_I101)\n", - "m.fs.I101.temperature.fix(303.2)\n", - "m.fs.I101.pressure.fix(350000)" + "tear_guesses = fix_inlet_states(m)" ], "outputs": [], "execution_count": 29 }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "Similarly, let us fix the hydrogen feed (`I102`) to the following conditions in the next cell:\n", - "
    \n", - "
  • FH2 = 0.30 mol/s
  • \n", - "
  • FCH4 = 0.02 mol/s
  • \n", - "
  • Remaining components = 1e-5 mol/s
  • \n", - "
  • T = 303.2 K
  • \n", - "
  • P = 350000 Pa
  • \n", - "
\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.429169Z", - "start_time": "2025-11-20T21:46:10.422052Z" - } - }, - "source": [ - "F_vap_hydrogen = 0.30\n", - "F_vap_methane = 0.020\n", - "\n", - "F_vap_non_zero = 1e-5\n", - "F_liq_non_zero = F_vap_non_zero\n", - "\n", - "F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero\n", - "F_liq_I102 = 2 * F_vap_non_zero\n", - "\n", - "m.fs.I102.flow_mol_phase[0, \"Vap\"].fix(F_vap_I102)\n", - "m.fs.I102.flow_mol_phase[0, \"Liq\"].fix(F_liq_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"benzene\"].fix(F_vap_non_zero / F_vap_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"toluene\"].fix(F_vap_non_zero / F_vap_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"hydrogen\"].fix(F_vap_hydrogen / F_vap_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Vap\", \"methane\"].fix(F_vap_methane / F_vap_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"benzene\"].fix(F_liq_non_zero / F_liq_I102)\n", - "m.fs.I102.mole_frac_phase_comp[0, \"Liq\", \"toluene\"].fix(F_liq_non_zero / F_liq_I102)\n", - "\n", - "m.fs.I102.temperature.fix(303.2)\n", - "m.fs.I102.pressure.fix(350000)" - ], - "outputs": [], - "execution_count": 30 - }, { "cell_type": "markdown", "metadata": {}, @@ -956,15 +890,15 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.441145Z", - "start_time": "2025-11-20T21:46:10.433569Z" + "end_time": "2026-01-13T00:12:30.047997400Z", + "start_time": "2026-01-13T00:12:30.039779600Z" } }, "source": [ "m.fs.H101.outlet.temperature.fix(600)" ], "outputs": [], - "execution_count": 31 + "execution_count": 30 }, { "cell_type": "markdown", @@ -977,8 +911,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.453419Z", - "start_time": "2025-11-20T21:46:10.445363Z" + "end_time": "2026-01-13T00:12:30.057083400Z", + "start_time": "2026-01-13T00:12:30.047997400Z" } }, "source": [ @@ -999,7 +933,7 @@ "m.fs.R101.heat_duty.fix(0)" ], "outputs": [], - "execution_count": 32 + "execution_count": 31 }, { "cell_type": "markdown", @@ -1012,8 +946,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.463025Z", - "start_time": "2025-11-20T21:46:10.457476Z" + "end_time": "2026-01-13T00:12:30.064658700Z", + "start_time": "2026-01-13T00:12:30.057083400Z" } }, "source": [ @@ -1021,7 +955,7 @@ "m.fs.F101.deltaP.fix(0)" ], "outputs": [], - "execution_count": 33 + "execution_count": 32 }, { "cell_type": "markdown", @@ -1050,15 +984,15 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.472509Z", - "start_time": "2025-11-20T21:46:10.467229Z" + "end_time": "2026-01-13T00:12:30.072457700Z", + "start_time": "2026-01-13T00:12:30.064658700Z" } }, "source": [ "# Todo: Set conditions for Flash F102" ], "outputs": [], - "execution_count": 34 + "execution_count": 33 }, { "cell_type": "code", @@ -1067,8 +1001,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.482109Z", - "start_time": "2025-11-20T21:46:10.475567Z" + "end_time": "2026-01-13T00:12:30.079966500Z", + "start_time": "2026-01-13T00:12:30.072457700Z" } }, "source": [ @@ -1076,7 +1010,7 @@ "m.fs.F102.deltaP.fix(-200000)" ], "outputs": [], - "execution_count": 35 + "execution_count": 34 }, { "cell_type": "markdown", @@ -1089,8 +1023,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.491620Z", - "start_time": "2025-11-20T21:46:10.485173Z" + "end_time": "2026-01-13T00:12:30.088622800Z", + "start_time": "2026-01-13T00:12:30.079966500Z" } }, "source": [ @@ -1098,7 +1032,7 @@ "m.fs.C101.outlet.pressure.fix(350000)" ], "outputs": [], - "execution_count": 36 + "execution_count": 35 }, { "cell_type": "markdown", @@ -1123,15 +1057,15 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.503512Z", - "start_time": "2025-11-20T21:46:10.495838Z" + "end_time": "2026-01-13T00:12:30.096269500Z", + "start_time": "2026-01-13T00:12:30.088622800Z" } }, "source": [ "# Todo: print the degrees of freedom" ], "outputs": [], - "execution_count": 37 + "execution_count": 36 }, { "cell_type": "code", @@ -1140,8 +1074,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.535421Z", - "start_time": "2025-11-20T21:46:10.507798Z" + "end_time": "2026-01-13T00:12:30.125313600Z", + "start_time": "2026-01-13T00:12:30.097272200Z" } }, "source": [ @@ -1156,7 +1090,7 @@ ] } ], - "execution_count": 38 + "execution_count": 37 }, { "cell_type": "code", @@ -1165,8 +1099,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.568992Z", - "start_time": "2025-11-20T21:46:10.542995Z" + "end_time": "2026-01-13T00:12:30.164032900Z", + "start_time": "2026-01-13T00:12:30.134372Z" } }, "source": [ @@ -1174,7 +1108,7 @@ "assert degrees_of_freedom(m) == 0" ], "outputs": [], - "execution_count": 39 + "execution_count": 38 }, { "cell_type": "markdown", @@ -1189,1057 +1123,237 @@ "It is important to determine the tear stream for a flowsheet which will be demonstrated below.\n", "\n", "\n", - "![](HDA_flowsheet.png)\n", - "\n", - "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or manually propagating through the flowsheet. Both methods will be shown.\n", - "\n", - "### 5.1 Sequential Decomposition\n", + "![](HDA_tear_stream.png)\n", "\n", - "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition\n" + "Currently, there are two methods of initializing a full flowsheet: using the sequential decomposition tool, or\n", + "manually propagating through the flowsheet. The tear stream in this example will be the stream from the mixer to the heater since that is where the\n", + "recycle stream first enters back into the main process.\n", + "\n" ] }, { - "cell_type": "markdown", "metadata": {}, - "source": [ - "Let us first create an object for the SequentialDecomposition and specify our options for this. We can also create a graph for our flowsheet to determine the tear set and order." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.578789Z", - "start_time": "2025-11-20T21:46:10.574025Z" - } - }, - "source": [ - "seq = SequentialDecomposition()\n", - "seq.options.select_tear_method = \"heuristic\"\n", - "seq.options.tear_method = \"Wegstein\"\n", - "seq.options.iterLim = 3\n", - "\n", - "# Using the SD tool\n", - "G = seq.create_graph(m)\n", - "heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", - "order = seq.calculation_order(G)" - ], - "outputs": [], - "execution_count": 40 - }, - { "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is the tear stream? Display tear set and order" - ] + "source": "First, we will highlight some helpful functions that are used in the initialization process." }, { - "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.588985Z", - "start_time": "2025-11-20T21:46:10.581810Z" + "end_time": "2026-01-13T00:12:30.174558500Z", + "start_time": "2026-01-13T00:12:30.166118800Z" } }, - "source": [ - "for o in heuristic_tear_set:\n", - " print(o.name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.s03\n" - ] - } - ], - "execution_count": 41 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What sequence did the SD tool determine to solve this flowsheet with the least number of tears? " - ] - }, - { "cell_type": "code", - "metadata": { - "scrolled": true, - "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.602315Z", - "start_time": "2025-11-20T21:46:10.599259Z" - } - }, "source": [ - "for o in order:\n", - " print(o[0].name)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fs.I101\n", - "fs.R101\n", - "fs.F101\n", - "fs.S101\n", - "fs.C101\n", - "fs.M101\n" - ] - } - ], - "execution_count": 42 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "\n", - "![](HDA_tear_stream.png) \n", - "\n", + "def initialize_unit(unit):\n", + " from idaes.core.util.exceptions import InitializationError\n", + " import idaes.logger as idaeslog\n", "\n", - "The SequentialDecomposition tool has determined that the tear stream is the mixer outlet. You can see this shown in the picture of the flowsheet above as the outlet of the mixer as the two lines crossing it identifying it as the tear stream. We will need to provide a reasonable guess for this." - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.620357Z", - "start_time": "2025-11-20T21:46:10.617116Z" - } - }, - "source": [ - "tear_guesses = {\n", - " \"flow_mol_phase\": {\n", - " (0, \"Liq\"): F_liq_I101,\n", - " (0, \"Vap\"): F_vap_I102,\n", - " },\n", - " \"mole_frac_phase_comp\": {\n", - " (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", - " (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", - " (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", - " (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", - " (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", - " (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", - " },\n", - " \"temperature\": {0: 303},\n", - " \"pressure\": {0: 350000},\n", - "}\n", + " optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 1000,\n", + " \"tol\": 1e-8,\n", + " }\n", "\n", - "# Pass the tear_guess to the SD tool\n", - "seq.set_guesses_for(m.fs.H101.inlet, tear_guesses)" - ], - "outputs": [], - "execution_count": 43 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we need to tell the tool how to initialize a particular unit. We will be writing a python function which takes in a \"unit\" and calls the initialize method on that unit. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:10.638254Z", - "start_time": "2025-11-20T21:46:10.635136Z" - } - }, - "source": [ - "def function(unit):\n", " try:\n", - " initializer = unit.default_initializer()\n", - " initializer.initialize(unit, output_level=idaeslog.INFO)\n", + " initializer = unit.default_initializer(solver_options=optarg)\n", + " initializer.initialize(unit, output_level=idaeslog.INFO_LOW)\n", " except InitializationError:\n", - " solver = get_solver()\n", + " solver = get_solver(solver_options=optarg)\n", " solver.solve(unit)" ], "outputs": [], - "execution_count": 44 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over and solve this flowsheet for us. " - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.022425Z", - "start_time": "2025-11-20T21:46:10.648251Z" - } - }, - "source": "seq.run(m, function)", - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:10 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", - "2025-11-20 14:46:11 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I101.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.I102.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:12 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", - "2025-11-20 14:46:13 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:14 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.H101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.R101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:15 [INFO] idaes.init.fs.F101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.purge_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101.recycle_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - \n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.C101.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_1_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_2_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.inlet_3_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101.mixed_state: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - \n", - "WARNING: Wegstein failed to converge in 3 iterations\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P103.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_in: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.F102.control_volume.properties_out: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Starting initialization routine\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: State variable initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P101.properties: Property initialization routine finished.\n", - "2025-11-20 14:46:16 [INFO] idaes.init.fs.P102.properties: Starting initialization routine\n", - "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Bubble, dew, and critical point initialization completed.\n", - "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Equilibrium temperature initialization completed.\n", - "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: State variable initialization completed.\n", - "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Phase equilibrium initialization completed.\n", - "2025-11-20 14:46:17 [INFO] idaes.init.fs.P102.properties: Property initialization routine finished.\n" - ] - } - ], - "execution_count": 45 + "execution_count": 39 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### 5.2 Manual Propagation Method\n", + "This first function will take any unit model and can either initialize the model with its respective default\n", + "initializer, or use a generic solver and the solve the current state of the unit model. Often times a direct\n", + "initialization method will fail while a solving method will converge so having the option for both is helpful.\n", "\n", - "This method uses a more direct approach to initialize the flowsheet, utilizing the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", - "Lets first import a helper function that will help us manually propagate and step through the flowsheet" - ] - }, - { - "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.069766Z", - "start_time": "2025-11-20T21:46:17.066725Z" - } - }, - "source": [ - "from idaes.core.util.initialization import propagate_state" - ], - "outputs": [], - "execution_count": 46 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can setup our initial guesses for the tear stream which we know is the outlet of the `Mixer` or the inlet of the `Heater`. We can use the same initial guesses used in the first method. We also want to ensure that the degrees of freedom are consistent while we manually initialize the model.\n", "\n", - "We will first ensure that are current degrees of freedom is still zero" + "### 5.1 Sequential Decomposition\n", + "\n", + "This section will demonstrate how to use the built-in sequential decomposition tool to initialize our flowsheet. Sequential Decomposition is a tool from Pyomo where the documentation can be found here https://Pyomo.readthedocs.io/en/stable/explanation/modeling/network.html#sequential-decomposition" ] }, { - "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.080343Z", - "start_time": "2025-11-20T21:46:17.077382Z" + "end_time": "2026-01-13T00:12:30.183526400Z", + "start_time": "2026-01-13T00:12:30.175559400Z" } }, - "source": "# print(f\"The DOF is {degrees_of_freedom(m)} initially\")", - "outputs": [], - "execution_count": 47 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can manually deactivate the tear stream, creating a separation between the `Mixer` and `Heater`. This should reduce the degrees of freedom by 10 since the inlet of the `Heater` now contains no values to solve the unit model. To deactivate a stream, simply use `m.fs.s03_expanded.deactivate()`. This expanded stream is just a different version of the `Arc` stream that is able to be deactivated." - ] - }, - { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.093180Z", - "start_time": "2025-11-20T21:46:17.089671Z" - } - }, "source": [ - "# m.fs.s03_expanded.deactivate()\n", - "#\n", - "# print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")" + "def automatic_propagation(m, tear_guesses):\n", + "\n", + " from pyomo.network import SequentialDecomposition\n", + "\n", + " seq = SequentialDecomposition()\n", + " seq.options.select_tear_method = \"heuristic\"\n", + " seq.options.tear_method = \"Wegstein\"\n", + " seq.options.iterLim = 5\n", + "\n", + " # Using the SD tool\n", + " G = seq.create_graph(m)\n", + " heuristic_tear_set = seq.tear_set_arcs(G, method=\"heuristic\")\n", + " order = seq.calculation_order(G)\n", + "\n", + " # Pass the tear_guess to the SD tool\n", + " seq.set_guesses_for(heuristic_tear_set[0].destination, tear_guesses)\n", + "\n", + " print(f'Tear Stream starts at: {heuristic_tear_set[0].destination.name}')\n", + "\n", + " for o in order:\n", + " print(o[0].name)\n", + "\n", + " seq.run(m, initialize_unit)\n" ], "outputs": [], - "execution_count": 48 + "execution_count": 40 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now we can provide the `Heater` inlet 10 guess values to bring the degrees of freedom back to 0 and start the manual initialization process. We can run this convenient loop to assign each of these guesses to the inlet of the heater." + "We are now ready to initialize our flowsheet in a sequential mode. Note that we specifically set the iteration limit\n", + "to be 5 as we are trying to use this tool only to get a good set of initial values such that IPOPT can then take over\n", + " and solve this flowsheet for us. Uncomment this function call to run the automatic propagation method" ] }, { - "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.105510Z", - "start_time": "2025-11-20T21:46:17.099824Z" + "end_time": "2026-01-13T00:12:30.191140600Z", + "start_time": "2026-01-13T00:12:30.184028800Z" } }, - "source": [ - "# tear_guesses = {\n", - "# \"flow_mol_phase\": {\n", - "# (0, \"Liq\"): F_liq_I101,\n", - "# (0, \"Vap\"): F_vap_I102,\n", - "#\n", - "# },\n", - "# \"mole_frac_phase_comp\": {\n", - "# (0, \"Liq\", \"benzene\"): 1e-5 / F_liq_I101,\n", - "# (0, \"Liq\", \"toluene\"): 0.30 / F_liq_I101,\n", - "# (0, \"Vap\", \"benzene\"): 1e-5 / F_vap_I102,\n", - "# (0, \"Vap\", \"toluene\"): 1e-5 / F_vap_I102,\n", - "# (0, \"Vap\", \"methane\"): 0.02 / F_vap_I102,\n", - "# (0, \"Vap\", \"hydrogen\"): 0.30 / F_vap_I102,\n", - "# },\n", - "# \"temperature\": {0: 303},\n", - "# \"pressure\": {0: 350000},\n", - "# }\n", - "#\n", - "# for k, v in tear_guesses.items():\n", - "# for k1, v1 in v.items():\n", - "# getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", - "#\n", - "# DOF_initial = degrees_of_freedom(m)\n", - "# print(f\"The DOF is {degrees_of_freedom(m)} after providing the initial guesses\")" - ], - "outputs": [], - "execution_count": 49 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next step is to manually initialize each unit model starting from the `Heater` and then propagate the connection between it and the next unit model. This manual process ensures a strict order to the user's specification if that is desired. The current standard for initializing a unit model is to use an initializer object most compatible for that unit model. This can most often be done by utilizing the `default_initializer()` method attached to the unit model and then to call the `initialize()` method with the unit model as the argument." - ] - }, - { "cell_type": "code", - "metadata": { - "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.117110Z", - "start_time": "2025-11-20T21:46:17.113630Z" - } - }, - "source": [ - "# m.fs.H101.default_initializer().initialize(m.fs.H101) # Initialize Heater\n", - "# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", - "#\n", - "# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor\n", - "# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", - "#\n", - "# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit\n", - "# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", - "# propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", - "#\n", - "# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter\n", - "# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", - "#\n", - "# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor\n", - "# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", - "#\n", - "# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet\n", - "# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", - "#\n", - "# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet\n", - "# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", - "#\n", - "# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer\n", - "# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", - "#\n", - "# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit\n", - "# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", - "# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", - "# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product" - ], + "source": "# automatic_propagation(m, tear_guesses)", "outputs": [], - "execution_count": 50 + "execution_count": 41 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now we solve the system to allow the outlet of the mixer to reach a converged congruence with the inlet of the heater." + "### 5.2 Manual Propagation Method\n", + "\n", + "This method uses a more direct approach to initialize the flowsheet, using the updated initializer method and propagating manually through the flowsheet and solving for the tear stream directly.\n", + "Lets define the function that will help us manually propagate and step through the flowsheet" ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.226222Z", - "start_time": "2025-11-20T21:46:17.129942Z" + "end_time": "2026-01-13T00:12:30.202920300Z", + "start_time": "2026-01-13T00:12:30.191140600Z" } }, "source": [ - "optarg = {\n", - " \"nlp_scaling_method\": \"user-scaling\",\n", - " \"OF_ma57_automatic_scaling\": \"yes\",\n", - " \"max_iter\": 300,\n", - " \"tol\": 1e-8,\n", - "}\n", - "solver = get_solver(\"ipopt_v2\", options=optarg)\n", - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: linear_solver=\"ma57\"\n", - "max_iter=300\n", - "nlp_scaling_method=\"user-scaling\"\n", - "tol=1e-08\n", - "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\"\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpvgsmpj67\\unknown.36084.37884.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma57.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 920\n", - "Number of nonzeros in inequality constraint Jacobian.: 0\n", - "Number of nonzeros in Lagrangian Hessian.............: 456\n", - "\n", - "Total number of variables............................: 218\n", - " variables with only lower bounds: 56\n", - " variables with lower and upper bounds: 147\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 218\n", - "Total number of inequality constraints...............: 0\n", - " inequality constraints with only lower bounds: 0\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 3.35e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - "Reallocating memory for MA57: lfact (10193)\n", - " 1 0.0000000e+00 1.07e+03 1.08e+01 -1.0 1.21e+03 - 8.49e-01 6.80e-01h 1\n", - " 2 0.0000000e+00 1.66e+02 4.55e+02 -1.0 7.65e+02 - 9.90e-01 8.44e-01h 1\n", - " 3 0.0000000e+00 5.53e+00 2.00e+02 -1.0 1.30e+02 - 9.90e-01 9.67e-01h 1\n", - " 4 0.0000000e+00 5.22e-02 8.91e+03 -1.0 4.05e+00 - 1.00e+00 9.91e-01h 1\n", - " 5 0.0000000e+00 1.46e-04 1.02e+04 -1.0 3.80e-02 - 1.00e+00 9.97e-01h 1\n", - " 6 0.0000000e+00 9.46e-11 6.27e-01 -1.0 1.06e-04 - 1.00e+00 1.00e+00h 1\n", - "\n", - "Number of Iterations....: 6\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 9.4587448984384537e-11 9.4587448984384537e-11\n", - "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 9.4587448984384537e-11 9.4587448984384537e-11\n", - "\n", - "\n", - "Number of objective function evaluations = 7\n", - "Number of objective gradient evaluations = 7\n", - "Number of equality constraint evaluations = 7\n", - "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 7\n", - "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 6\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.009\n", - "Total CPU secs in NLP function evaluations = 0.001\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } + "def manual_propagation(m, tear_guesses):\n", + " from idaes.core.util.initialization import propagate_state\n", + "\n", + " print(f\"The DOF is {degrees_of_freedom(m)} initially\")\n", + " m.fs.s03_expanded.deactivate()\n", + " print(f\"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream\")\n", + "\n", + " for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.s03.destination, k)[k1].fix(v1)\n", + "\n", + " print(f\"The DOF is {degrees_of_freedom(m)} after setting the tear stream\")\n", + "\n", + " optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " # \"tol\": 1e-10,\n", + " }\n", + "\n", + " solver = get_solver(solver_options=optarg)\n", + "\n", + " initialize_unit(m.fs.H101) # Initialize Heater\n", + " propagate_state(m.fs.s04) # Establish connection between Heater and Reactor\n", + " initialize_unit(m.fs.R101) # Initialize Reactor\n", + " propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit\n", + " initialize_unit(m.fs.F101) # Initialize First Flash Unit\n", + " propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter\n", + " propagate_state(m.fs.s07) # Establish connection between First Flash Unit and Second Flash Unit\n", + " initialize_unit(m.fs.S101) # Initialize Splitter\n", + " propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor\n", + " initialize_unit(m.fs.C101) # Initialize Compressor\n", + " propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer\n", + " initialize_unit(m.fs.I101) # Initialize Toluene Inlet\n", + " propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer\n", + " initialize_unit(m.fs.I102) # Initialize Hydrogen Inlet\n", + " propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer\n", + " initialize_unit(m.fs.M101) # Initialize Mixer\n", + " propagate_state(m.fs.s03) # Establish connection between Mixer and Heater\n", + " solver.solve(m.fs.F102)\n", + " propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product\n", + " propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product\n", + " propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product\n", + "\n", + " optarg = {\n", + " \"nlp_scaling_method\": \"user-scaling\",\n", + " \"OF_ma57_automatic_scaling\": \"yes\",\n", + " \"max_iter\": 300,\n", + " \"tol\": 1e-8,\n", + " }\n", + " solver = get_solver(\"ipopt_v2\", options=optarg)\n", + " solver.solve(m, tee=False)\n", + "\n", + " for k, v in tear_guesses.items():\n", + " for k1, v1 in v.items():\n", + " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", + "\n", + " m.fs.s03_expanded.activate()\n", + " print(\n", + " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", + " )" ], - "execution_count": 51 + "outputs": [], + "execution_count": 42 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now that the flowsheet is initialized, we can unfix the guesses for the `Heater` and reactive the tear stream to complete the final solve." + "It will first show that the degrees of freedom is correctly at 0 before any streams are deactivated. Once the tear\n", + "stream is deactivated though, the degrees of freedom will be 10. That means 10 variables will have to be defined with\n", + " the tear guesses `tear_guesses`. Then each unit model can be initialized with our same helper function and then can\n", + " propogate the corresponding connection to the following unit models. At the end, the whole flowsheet is solved,\n", + " giving a much better chance for the recycle stream to be used correctly the flowsheet to converge." ] }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.258332Z", - "start_time": "2025-11-20T21:46:17.233298Z" + "end_time": "2026-01-13T00:12:32.448895Z", + "start_time": "2026-01-13T00:12:30.204922600Z" } }, - "source": [ - "for k, v in tear_guesses.items():\n", - " for k1, v1 in v.items():\n", - " getattr(m.fs.H101.inlet, k)[k1].unfix()\n", - "\n", - "m.fs.s03_expanded.activate()\n", - "print(\n", - " f\"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream\"\n", - ")" - ], + "source": "manual_propagation(m, tear_guesses)", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "The DOF is 0 initially\n", + "The DOF is 10 after deactivating the tear stream\n", + "The DOF is 0 after setting the tear stream\n", "The DOF is 0 after unfixing the values and reactivating the tear stream\n" ] } ], - "execution_count": 52 + "execution_count": 43 }, { "cell_type": "markdown", @@ -2261,8 +1375,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.268422Z", - "start_time": "2025-11-20T21:46:17.265316Z" + "end_time": "2026-01-13T00:12:32.467353Z", + "start_time": "2026-01-13T00:12:32.458309200Z" } }, "source": [ @@ -2274,7 +1388,7 @@ "}" ], "outputs": [], - "execution_count": 53 + "execution_count": 44 }, { "cell_type": "markdown", @@ -2302,8 +1416,8 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.285774Z", - "start_time": "2025-11-20T21:46:17.281657Z" + "end_time": "2026-01-13T00:12:32.476284300Z", + "start_time": "2026-01-13T00:12:32.467353Z" } }, "source": [ @@ -2312,7 +1426,7 @@ "# Solve the model" ], "outputs": [], - "execution_count": 54 + "execution_count": 45 }, { "cell_type": "code", @@ -2321,8 +1435,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.382669Z", - "start_time": "2025-11-20T21:46:17.293013Z" + "end_time": "2026-01-13T00:12:32.967264500Z", + "start_time": "2026-01-13T00:12:32.476788800Z" } }, "source": [ @@ -2330,7 +1444,7 @@ "solver = get_solver(\"ipopt_v2\", options=optarg)\n", "\n", "# Solve the model\n", - "results = solver.solve(m, tee=True)" + "results = solver.solve(m, tee=False)" ], "outputs": [ { @@ -2341,9 +1455,9 @@ "max_iter=1000\n", "nlp_scaling_method=\"user-scaling\"\n", "tol=1e-08\n", - "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\"\n", + "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpjzf4e172\\unknown.31496.43076.opt\"\n", "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpi86o_z2t\\unknown.36084.37884.opt\".\n", + "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpjzf4e172\\unknown.31496.43076.opt\".\n", "\n", "\n", "******************************************************************************\n", @@ -2372,7 +1486,7 @@ "\n", "Total number of variables............................: 218\n", " variables with only lower bounds: 56\n", - " variables with lower and upper bounds: 147\n", + " variables with lower and upper bounds: 155\n", " variables with only upper bounds: 0\n", "Total number of equality constraints.................: 218\n", "Total number of inequality constraints...............: 0\n", @@ -2381,38 +1495,273 @@ " inequality constraints with only upper bounds: 0\n", "\n", "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 0.0000000e+00 1.64e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 0 0.0000000e+00 8.17e+03 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", "Reallocating memory for MA57: lfact (10193)\n", - " 1 0.0000000e+00 1.84e+01 4.18e+00 -1.0 4.14e-01 - 9.90e-01 9.89e-01h 1\n", - " 2 0.0000000e+00 1.82e-01 3.87e+00 -1.0 3.76e-01 - 9.90e-01 9.90e-01h 1\n", - " 3 0.0000000e+00 6.96e-04 4.53e+02 -1.0 3.70e-02 - 9.92e-01 9.96e-01h 1\n", - " 4 0.0000000e+00 4.52e-09 8.75e-01 -1.0 3.82e-04 - 1.00e+00 1.00e+00h 1\n", + " 1 0.0000000e+00 7.12e+03 2.01e+02 -1.0 4.35e+04 - 4.68e-02 1.56e-01h 1\n", + " 2 0.0000000e+00 7.12e+03 2.74e+02 -1.0 4.20e+05 - 9.82e-04 5.24e-04h 1\n", + " 3 0.0000000e+00 7.11e+03 2.06e+03 -1.0 4.26e+05 - 1.43e-05 1.49e-03f 1\n", + " 4 0.0000000e+00 7.09e+03 1.83e+03 -1.0 3.65e+04 - 5.78e-03 2.02e-03h 1\n", + " 5 0.0000000e+00 7.09e+03 1.82e+03 -1.0 1.61e+05 - 4.69e-04 1.23e-05h 1\n", + " 6r 0.0000000e+00 7.09e+03 9.99e+02 3.9 0.00e+00 - 0.00e+00 6.02e-08R 2\n", + " 7r 0.0000000e+00 6.68e+03 9.98e+02 3.9 7.11e+06 - 5.22e-04 1.63e-04f 1\n", + " 8r 0.0000000e+00 4.74e+04 9.98e+02 3.9 3.89e+06 - 2.84e-04 7.21e-04f 1\n", + " 9r 0.0000000e+00 4.77e+04 1.78e+04 3.9 1.73e+06 - 4.34e-02 5.81e-04f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 10r 0.0000000e+00 4.55e+04 4.83e+04 3.2 4.71e+04 - 2.92e-01 4.47e-02f 1\n", + " 11r 0.0000000e+00 7.86e+04 3.48e+04 3.2 3.13e+02 - 4.51e-01 3.27e-01f 1\n", + " 12r 0.0000000e+00 4.85e+04 2.80e+04 3.2 5.27e+01 - 5.22e-01 2.61e-01f 1\n", + " 13r 0.0000000e+00 1.68e+05 1.76e+04 3.2 1.46e+02 - 8.30e-01 4.81e-01f 1\n", + " 14r 0.0000000e+00 8.02e+04 3.21e+03 3.2 1.42e+02 - 7.28e-01 1.00e+00f 1\n", + " 15r 0.0000000e+00 1.89e+05 6.22e+04 3.2 1.06e+02 - 4.83e-01 1.00e+00f 1\n", + " 16r 0.0000000e+00 1.77e+05 5.95e+04 3.2 1.08e+02 0.0 9.89e-02 6.28e-02h 1\n", + " 17r 0.0000000e+00 1.03e+05 3.98e+04 3.2 8.09e+01 - 7.18e-01 4.22e-01h 1\n", + " 18r 0.0000000e+00 8.88e+04 8.50e+04 3.2 1.59e+02 - 2.14e-01 1.36e-01h 1\n", + " 19r 0.0000000e+00 5.30e+04 1.71e+06 3.2 8.69e+01 - 3.02e-02 3.51e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 20r 0.0000000e+00 1.40e+04 2.20e+05 3.2 1.08e+01 2.2 6.72e-01 8.78e-01f 1\n", + " 21r 0.0000000e+00 9.61e+03 9.51e+04 2.5 1.06e+01 1.8 9.32e-01 4.27e-01f 1\n", + " 22r 0.0000000e+00 1.83e+04 3.37e+04 2.5 1.51e+01 1.3 1.00e+00 6.41e-01f 1\n", + " 23r 0.0000000e+00 3.76e+03 1.35e+03 2.5 4.90e+00 0.8 1.00e+00 1.00e+00f 1\n", + " 24r 0.0000000e+00 1.38e+05 2.72e+04 2.5 1.06e+02 - 3.87e-01 1.00e+00f 1\n", + " 25r 0.0000000e+00 1.06e+05 2.11e+04 2.5 5.11e+01 1.2 2.99e-01 2.35e-01h 1\n", + " 26r 0.0000000e+00 9.35e+04 1.83e+04 2.5 3.27e+01 2.6 6.94e-02 1.19e-01h 1\n", + " 27r 0.0000000e+00 9.23e+03 3.61e+03 2.5 2.06e+01 2.1 2.35e-01 1.00e+00h 1\n", + " 28r 0.0000000e+00 9.21e+03 6.60e+03 2.5 9.05e+02 - 1.37e-01 3.89e-03f 1\n", + " 29r 0.0000000e+00 6.69e+04 1.34e+04 2.5 1.58e+02 - 3.39e-01 2.01e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 30r 0.0000000e+00 7.42e+01 3.52e+04 2.5 3.26e-01 1.6 4.89e-01 1.00e+00f 1\n", + " 31r 0.0000000e+00 9.36e+03 1.66e+02 2.5 1.29e+01 - 1.00e+00 1.00e+00f 1\n", + " 32r 0.0000000e+00 9.30e+01 3.75e+00 2.5 1.85e+00 - 1.00e+00 1.00e+00h 1\n", + " 33r 0.0000000e+00 8.97e+03 9.16e+02 0.4 4.59e+01 - 7.14e-01 7.41e-01f 1\n", + " 34r 0.0000000e+00 7.19e+03 3.37e+02 0.4 2.34e+03 - 7.23e-01 6.68e-01f 1\n", + " 35r 0.0000000e+00 5.64e+03 5.42e+02 0.4 7.33e+02 - 6.81e-01 5.42e-01f 1\n", + " 36r 0.0000000e+00 1.10e+03 1.79e+02 0.4 2.38e-01 2.0 6.12e-01 8.67e-01f 1\n", + " 37r 0.0000000e+00 3.67e+02 1.23e+02 0.4 9.76e-02 2.5 9.90e-01 8.27e-01f 1\n", + " 38r 0.0000000e+00 2.93e+01 3.80e+02 0.4 2.55e-01 2.0 5.41e-01 1.00e+00f 1\n", + " 39r 0.0000000e+00 2.58e+01 7.52e+02 0.4 2.70e+00 2.4 4.08e-02 9.27e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 40r 0.0000000e+00 1.03e+01 2.85e+02 0.4 8.74e-02 2.8 7.74e-01 6.78e-01f 1\n", + " 41r 0.0000000e+00 4.85e+00 8.16e+01 0.4 2.96e-01 2.4 7.04e-01 7.21e-01f 1\n", + " 42r 0.0000000e+00 1.15e+02 7.32e+01 -0.3 1.76e-01 1.9 7.14e-01 7.59e-01f 1\n", + " 43r 0.0000000e+00 2.10e+02 3.61e+02 -0.3 4.28e-01 1.4 7.77e-01 1.77e-01f 1\n", + " 44r 0.0000000e+00 1.51e+02 6.63e+01 -0.3 4.68e-01 0.9 1.00e+00 8.94e-01f 1\n", + " 45r 0.0000000e+00 9.19e+00 1.85e+01 -0.3 1.49e-01 1.3 1.00e+00 1.00e+00f 1\n", + " 46r 0.0000000e+00 5.62e+00 5.71e+01 -0.3 1.05e+00 0.9 4.17e-01 3.89e-01h 1\n", + " 47r 0.0000000e+00 1.98e+01 3.77e+01 -0.3 7.16e-01 0.4 1.00e+00 1.00e+00f 1\n", + " 48r 0.0000000e+00 1.82e+01 6.27e+02 -0.3 9.97e+00 -0.1 4.98e-02 8.93e-02h 1\n", + " 49r 0.0000000e+00 1.72e+01 5.84e+02 -0.3 1.90e+00 1.2 4.67e-02 4.96e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 50r 0.0000000e+00 1.16e+01 7.04e+02 -0.3 1.10e+00 0.8 6.53e-01 4.12e-01f 1\n", + " 51r 0.0000000e+00 1.08e+01 6.28e+02 -0.3 2.94e-01 2.1 3.66e-01 6.78e-02f 1\n", + " 52r 0.0000000e+00 6.69e+00 7.88e+02 -0.3 4.74e-01 1.6 5.14e-01 6.14e-01f 1\n", + " 53r 0.0000000e+00 6.34e+00 1.39e+03 -0.3 6.49e-02 2.9 1.00e+00 5.17e-02h 1\n", + " 54r 0.0000000e+00 5.30e-01 7.34e+02 -0.3 1.91e-01 2.5 5.47e-01 1.00e+00f 1\n", + " 55r 0.0000000e+00 5.30e-01 8.37e+02 -0.3 1.09e-01 2.9 1.00e+00 1.86e-01f 1\n", + " 56r 0.0000000e+00 6.24e-01 3.25e+02 -0.3 2.18e-01 2.4 7.22e-01 7.62e-01f 1\n", + " 57r 0.0000000e+00 5.84e-01 1.25e+03 -0.3 1.10e-01 2.8 3.44e-01 6.58e-02f 1\n", + " 58r 0.0000000e+00 1.84e+00 9.86e+02 -0.3 6.56e-01 2.4 4.76e-01 1.66e-01f 1\n", + " 59r 0.0000000e+00 9.98e+00 7.31e+02 -0.3 2.98e-01 1.9 3.81e-01 1.96e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 60r 0.0000000e+00 2.33e+01 6.73e+02 -0.3 2.93e+00 1.4 1.64e-03 2.62e-02f 1\n", + " 61r 0.0000000e+00 2.09e+02 6.21e+02 -0.3 3.68e+00 1.8 2.80e-02 4.31e-02f 1\n", + " 62r 0.0000000e+00 2.06e+02 4.81e+02 -0.3 4.45e-01 1.4 4.03e-01 1.68e-02h 1\n", + " 63r 0.0000000e+00 1.65e+02 3.87e+02 -0.3 1.11e+00 0.9 1.92e-02 1.96e-01f 1\n", + " 64r 0.0000000e+00 1.50e+02 3.08e+02 -0.3 1.85e+00 0.4 2.04e-01 2.07e-01f 1\n", + " 65r 0.0000000e+00 1.42e+02 2.98e+02 -0.3 1.20e+00 1.7 3.04e-02 5.07e-02f 1\n", + " 66r 0.0000000e+00 7.46e+01 5.29e+02 -0.3 5.27e-02 2.2 9.16e-01 4.78e-01f 1\n", + " 67r 0.0000000e+00 5.57e+01 4.82e+02 -0.3 1.72e-01 1.7 9.61e-01 2.54e-01f 1\n", + " 68r 0.0000000e+00 2.98e+00 1.46e+02 -0.3 2.22e-01 1.2 1.00e+00 9.79e-01f 1\n", + " 69r 0.0000000e+00 6.01e+00 2.34e+02 -0.3 4.07e-01 0.7 5.24e-01 4.28e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 70r 0.0000000e+00 1.07e+02 5.44e+02 -0.3 1.11e+00 0.3 7.04e-01 1.00e+00f 1\n", + " 71r 0.0000000e+00 2.25e+01 7.39e+02 -0.3 1.39e-01 1.6 3.98e-01 7.90e-01f 1\n", + " 72r 0.0000000e+00 2.07e+01 7.10e+02 -0.3 6.94e-01 1.1 2.42e-01 8.16e-02f 1\n", + " 73r 0.0000000e+00 4.67e+01 3.79e+02 -0.3 3.86e-01 0.6 6.91e-01 1.00e+00f 1\n", + " 74r 0.0000000e+00 7.77e+01 2.65e+02 -0.3 9.27e-01 0.2 4.94e-01 4.38e-01h 1\n", + " 75r 0.0000000e+00 7.62e+01 2.61e+02 -0.3 3.81e+00 0.6 2.20e-02 3.06e-02f 2\n", + " 76r 0.0000000e+00 5.81e+01 2.16e+02 -0.3 1.57e-01 1.9 3.64e-01 2.38e-01f 1\n", + " 77r 0.0000000e+00 1.97e+01 1.33e+02 -0.3 1.61e-01 1.4 1.00e+00 6.92e-01f 1\n", + " 78r 0.0000000e+00 4.47e+01 2.11e+02 -0.3 8.61e-01 1.0 7.64e-01 4.57e-01f 1\n", + " 79r 0.0000000e+00 2.75e+02 1.68e+02 -0.3 2.89e+00 0.5 1.90e-01 1.97e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 80r 0.0000000e+00 1.57e+01 5.93e+01 -0.3 1.06e-01 1.8 1.00e+00 1.00e+00f 1\n", + " 81r 0.0000000e+00 4.52e+00 7.54e+00 -0.3 3.54e-01 1.3 1.00e+00 1.00e+00h 1\n", + " 82r 0.0000000e+00 1.51e+01 6.83e+01 -1.0 1.48e-01 1.8 6.09e-01 6.86e-01f 1\n", + " 83r 0.0000000e+00 9.47e+00 2.62e+01 -1.0 5.68e-02 2.2 1.00e+00 8.94e-01f 1\n", + " 84r 0.0000000e+00 2.30e+01 2.17e+01 -1.0 4.35e-01 1.7 1.62e-01 1.76e-01f 1\n", + " 85r 0.0000000e+00 1.67e+01 1.83e+02 -1.0 8.29e-02 2.1 1.00e+00 4.80e-01f 1\n", + " 86r 0.0000000e+00 5.83e+01 5.12e+02 -1.0 3.20e-01 1.7 6.90e-01 3.58e-01f 1\n", + " 87r 0.0000000e+00 1.07e+02 1.19e+03 -1.0 1.30e+01 1.2 2.99e-02 1.02e-02f 1\n", + " 88r 0.0000000e+00 1.05e+02 3.60e+02 -1.0 2.66e+00 0.7 1.00e+00 2.59e-02f 1\n", + " 89r 0.0000000e+00 4.13e+02 4.81e+02 -1.0 7.27e+00 0.2 1.00e+00 4.22e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 90r 0.0000000e+00 4.12e+02 4.73e+02 -1.0 7.91e+01 -0.3 2.91e-03 3.88e-03f 1\n", + " 91r 0.0000000e+00 3.90e+02 5.09e+02 -1.0 1.05e+00 1.1 1.00e+00 5.42e-02f 1\n", + " 92r 0.0000000e+00 6.42e+02 1.96e+01 -1.0 3.03e+00 0.6 1.00e+00 1.00e+00f 1\n", + " 93r 0.0000000e+00 1.54e+03 5.81e+02 -1.0 1.25e+01 0.1 9.40e-02 6.11e-01f 1\n", + " 94r 0.0000000e+00 1.52e+03 5.61e+02 -1.0 9.43e+00 0.5 1.64e-02 8.32e-03f 1\n", + " 95r 0.0000000e+00 1.38e+03 3.41e+02 -1.0 2.32e+01 0.1 3.92e-01 1.27e-01f 1\n", + " 96r 0.0000000e+00 1.38e+03 3.72e+02 -1.0 5.95e+00 0.5 3.61e-01 4.34e-03h 1\n", + " 97r 0.0000000e+00 1.28e+03 2.01e+02 -1.0 1.09e+01 0.0 4.23e-02 1.05e-01f 1\n", + " 98r 0.0000000e+00 9.89e+02 4.20e+02 -1.0 4.94e+00 0.4 3.76e-02 2.66e-01f 1\n", + " 99r 0.0000000e+00 8.96e+02 4.65e+02 -1.0 2.96e+00 0.9 2.83e-01 9.51e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 100r 0.0000000e+00 8.38e+02 1.08e+03 -1.0 3.79e+00 0.4 5.07e-01 6.96e-02h 1\n", + " 101r 0.0000000e+00 1.19e+03 6.44e+02 -1.0 9.81e+00 -0.1 3.71e-01 3.57e-01f 1\n", + " 102r 0.0000000e+00 1.19e+03 5.28e+02 -1.0 1.78e+01 -0.6 7.44e-03 6.07e-02f 1\n", + " 103r 0.0000000e+00 1.02e+03 3.34e+02 -1.0 2.10e+01 -1.0 4.17e-02 1.21e-01f 1\n", + " 104r 0.0000000e+00 9.98e+02 8.36e+02 -1.0 8.35e+00 -0.6 4.71e-01 1.95e-02h 1\n", + " 105r 0.0000000e+00 6.83e+02 6.45e+02 -1.0 1.30e+01 -1.1 5.71e-02 2.84e-01f 1\n", + " 106r 0.0000000e+00 8.65e+02 1.14e+03 -1.0 8.25e+00 -0.7 1.61e-01 6.21e-01f 1\n", + " 107r 0.0000000e+00 7.16e+02 9.70e+02 -1.0 4.28e+00 -0.2 1.93e-01 1.57e-01h 1\n", + " 108r 0.0000000e+00 6.31e+02 8.28e+02 -1.0 6.49e+00 -0.7 6.61e-02 1.81e-01h 1\n", + " 109r 0.0000000e+00 4.55e+02 1.19e+03 -1.0 2.95e+00 -0.3 1.88e-01 8.74e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 110r 0.0000000e+00 1.83e+02 4.89e+02 -1.0 1.15e-01 1.9 6.47e-01 5.98e-01h 1\n", + " 111r 0.0000000e+00 3.73e+01 1.31e+02 -1.0 8.98e-02 1.5 1.00e+00 7.95e-01h 1\n", + " 112r 0.0000000e+00 7.86e+00 8.49e+01 -1.0 7.76e-02 1.9 9.93e-01 7.86e-01h 1\n", + " 113r 0.0000000e+00 2.86e+00 1.42e+01 -1.0 1.00e-01 1.4 1.00e+00 1.00e+00h 1\n", + " 114r 0.0000000e+00 2.89e+00 2.59e+00 -1.0 3.00e-01 0.9 1.00e+00 1.00e+00f 1\n", + " 115r 0.0000000e+00 5.21e+01 6.10e+00 -1.0 8.19e-01 0.5 1.00e+00 1.00e+00f 1\n", + " 116r 0.0000000e+00 1.36e+02 4.46e+02 -1.0 2.16e+00 -0.0 2.00e-01 5.43e-01f 1\n", + " 117r 0.0000000e+00 2.35e+01 1.35e+02 -1.0 3.81e-02 2.2 6.64e-01 8.26e-01h 1\n", + " 118r 0.0000000e+00 1.45e+01 6.04e+02 -1.0 4.14e-01 1.7 1.30e-01 6.39e-01f 1\n", + " 119r 0.0000000e+00 7.09e+01 1.51e+03 -1.0 1.49e+00 2.2 9.44e-02 3.42e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 120r 0.0000000e+00 6.91e+01 1.74e+03 -1.0 3.65e-01 2.6 2.02e-01 2.71e-02f 1\n", + " 121r 0.0000000e+00 6.89e+01 1.47e+03 -1.0 1.29e+00 2.1 8.23e-04 3.05e-03f 1\n", + " 122r 0.0000000e+00 6.81e+01 2.26e+03 -1.0 1.01e+00 1.6 5.80e-02 1.11e-02f 1\n", + " 123r 0.0000000e+00 5.53e+01 8.13e+02 -1.0 9.48e-01 1.2 1.55e-02 1.67e-01f 1\n", + " 124r 0.0000000e+00 4.39e+01 6.51e+02 -1.0 6.05e-01 0.7 2.20e-01 1.95e-01f 1\n", + " 125r 0.0000000e+00 3.95e+01 5.85e+02 -1.0 1.15e+00 0.2 4.00e-01 9.82e-02f 1\n", + " 126r 0.0000000e+00 5.31e+01 2.97e+02 -1.0 1.75e+00 -0.3 4.11e-03 3.31e-01f 1\n", + " 127r 0.0000000e+00 5.22e+01 2.92e+02 -1.0 1.49e+00 0.2 4.34e-02 1.79e-02h 1\n", + " 128r 0.0000000e+00 5.15e+01 2.70e+02 -1.0 9.28e+00 -0.3 1.26e-01 3.54e-02f 1\n", + " 129r 0.0000000e+00 2.87e+01 8.41e+01 -1.0 1.20e+00 0.1 9.87e-01 7.24e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 130r 0.0000000e+00 5.74e+01 7.12e+01 -1.0 2.02e+00 -0.4 1.00e+00 3.08e-01h 1\n", + " 131r 0.0000000e+00 1.40e+03 2.57e+01 -1.0 6.81e+00 -0.9 6.75e-01 8.23e-01f 1\n", + " 132r 0.0000000e+00 1.35e+03 2.54e+01 -1.0 1.62e+01 -1.3 1.03e-01 3.34e-02h 1\n", + " 133r 0.0000000e+00 1.23e+03 3.95e+01 -1.0 7.83e+00 -0.9 7.40e-01 6.60e-01h 1\n", + " 134r 0.0000000e+00 1.19e+03 3.30e+02 -1.0 1.81e+01 -1.4 3.93e-01 5.73e-02h 1\n", + " 135r 0.0000000e+00 1.18e+03 3.16e+02 -1.0 1.12e+02 -1.9 2.06e-02 2.35e-02h 1\n", + " 136r 0.0000000e+00 3.04e+03 1.74e+02 -1.0 1.66e+01 -1.4 6.20e-01 5.67e-01h 1\n", + " 137r 0.0000000e+00 3.10e+03 7.86e+01 -1.0 4.18e+02 -1.9 4.32e-04 5.13e-03f 1\n", + " 138r 0.0000000e+00 3.15e+03 8.59e+01 -1.0 2.08e+01 -1.5 6.10e-01 3.20e-01f 1\n", + " 139r 0.0000000e+00 6.79e+03 9.92e+01 -1.0 6.29e+01 -2.0 5.13e-01 5.43e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 140r 0.0000000e+00 1.99e+03 2.93e+02 -1.0 1.82e-01 1.2 9.52e-01 7.07e-01h 1\n", + " 141r 0.0000000e+00 4.14e-01 6.19e+01 -1.0 4.03e-02 1.6 9.05e-01 1.00e+00h 1\n", + " 142r 0.0000000e+00 5.40e-01 1.00e+01 -1.0 7.66e-02 1.1 1.00e+00 1.00e+00h 1\n", + " 143r 0.0000000e+00 1.87e+00 7.98e-01 -1.0 1.80e-01 0.6 1.00e+00 1.00e+00h 1\n", + " 144r 0.0000000e+00 1.04e+01 9.40e-01 -1.0 4.36e-01 0.2 1.00e+00 1.00e+00h 1\n", + " 145r 0.0000000e+00 3.19e+01 4.06e+00 -1.0 9.89e-01 -0.3 1.00e+00 1.00e+00h 1\n", + " 146r 0.0000000e+00 2.28e+02 6.27e+00 -1.0 3.02e+00 -0.8 1.00e+00 9.35e-01h 1\n", + " 147r 0.0000000e+00 7.58e+02 1.93e+02 -1.0 1.17e+01 -1.3 1.00e+00 5.43e-01h 1\n", + " 148r 0.0000000e+00 7.62e+02 6.49e+02 -1.0 5.17e+01 -1.7 4.76e-01 9.10e-02h 1\n", + " 149r 0.0000000e+00 5.18e+03 4.98e+02 -1.0 3.35e+02 -2.2 2.78e-02 1.43e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 150r 0.0000000e+00 5.19e+03 7.41e+02 -1.0 1.23e+03 -2.7 1.42e-02 2.95e-02f 1\n", + " 151r 0.0000000e+00 6.87e+03 9.57e+02 -1.0 1.12e+03 -2.3 1.35e-03 3.17e-02f 1\n", + " 152r 0.0000000e+00 6.85e+03 8.50e+02 -1.0 1.37e+02 -1.8 3.99e-01 4.06e-03h 1\n", + " 153r 0.0000000e+00 6.72e+03 9.57e+02 -1.0 4.39e+02 -2.3 1.18e-01 1.81e-02h 1\n", + " 154r 0.0000000e+00 6.40e+03 1.13e+03 -1.0 1.07e+04 - 1.49e-01 4.89e-02f 1\n", + " 155r 0.0000000e+00 5.62e+03 9.92e+02 -1.0 9.94e+03 - 1.20e-01 1.22e-01f 1\n", + " 156r 0.0000000e+00 5.58e+03 9.64e+02 -1.0 3.35e+03 - 1.73e-03 7.88e-03h 1\n", + " 157r 0.0000000e+00 5.58e+03 9.64e+02 -1.0 2.55e+05 -2.8 2.32e-05 2.33e-05f 1\n", + " 158r 0.0000000e+00 5.55e+03 1.02e+03 -1.0 4.99e+02 -3.3 2.90e-02 5.00e-03h 1\n", + " 159r 0.0000000e+00 4.91e+03 9.36e+02 -1.0 1.06e+02 -3.8 1.63e-01 1.16e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 160r 0.0000000e+00 4.19e+03 7.63e+02 -1.0 1.75e+02 -2.4 1.15e-02 1.48e-01h 1\n", + " 161r 0.0000000e+00 4.18e+03 7.94e+02 -1.0 4.34e+02 -2.9 3.97e-02 1.46e-03h 1\n", + " 162r 0.0000000e+00 2.31e+03 3.53e+02 -1.0 5.33e+03 - 1.01e-01 4.63e-01h 1\n", + " 163r 0.0000000e+00 2.04e+03 5.97e+02 -1.0 3.18e+03 - 1.73e-01 1.20e-01h 1\n", + " 164r 0.0000000e+00 1.26e+03 3.46e+02 -1.0 3.03e+03 - 4.18e-01 4.11e-01h 1\n", + " 165r 0.0000000e+00 1.24e+03 3.20e+02 -1.0 2.32e+03 - 1.97e-03 1.44e-02h 1\n", + " 166r 0.0000000e+00 1.17e+03 4.22e+02 -1.0 2.31e+03 - 3.37e-01 5.42e-02h 1\n", + " 167r 0.0000000e+00 1.04e+03 6.87e+02 -1.0 1.74e+03 - 9.08e-01 1.16e-01h 1\n", + " 168r 0.0000000e+00 3.09e+02 4.10e+02 -1.0 1.64e+03 - 4.91e-01 8.06e-01h 1\n", + " 169r 0.0000000e+00 3.95e+02 5.59e+02 -1.0 2.46e+03 - 1.49e-02 2.83e-02f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 170r 0.0000000e+00 2.99e+02 7.69e+01 -1.0 4.31e+02 - 8.88e-01 1.00e+00f 1\n", + " 171r 0.0000000e+00 1.65e+02 3.84e+02 -1.0 4.91e-01 0.2 1.00e+00 4.50e-01h 1\n", + " 172r 0.0000000e+00 1.87e-01 5.61e+01 -1.0 2.62e+00 - 1.00e+00 1.00e+00h 1\n", + " 173r 0.0000000e+00 1.87e-01 2.09e+01 -1.0 8.62e-01 - 1.00e+00 1.00e+00h 1\n", + " 174r 0.0000000e+00 1.87e-01 1.77e+00 -1.0 9.94e-02 - 1.00e+00 1.00e+00h 1\n", + " 175r 0.0000000e+00 7.96e+00 5.39e+00 -1.7 1.21e+01 - 1.00e+00 9.98e-01f 1\n", + " 176r 0.0000000e+00 2.31e+02 1.33e+02 -1.7 1.26e+04 - 3.42e-01 1.24e-01f 1\n", + " 177r 0.0000000e+00 2.38e+02 3.38e+02 -1.7 1.05e+04 - 6.40e-01 3.94e-02f 1\n", + " 178r 0.0000000e+00 2.37e+02 3.35e+02 -1.7 7.28e+03 - 9.97e-02 1.97e-03h 1\n", + " 179r 0.0000000e+00 2.11e+02 3.90e+02 -1.7 3.85e+03 - 5.39e-01 1.07e-01h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 180r 0.0000000e+00 3.16e+02 4.17e+02 -1.7 3.82e+03 - 1.28e-02 9.51e-01f 1\n", + " 181r 0.0000000e+00 1.07e+03 2.19e+02 -1.7 3.96e+03 - 4.42e-01 4.76e-01h 1\n", + " 182r 0.0000000e+00 1.05e+03 2.05e+02 -1.7 1.41e+03 - 4.64e-01 2.04e-02h 1\n", + " 183r 0.0000000e+00 4.56e+02 1.83e+02 -1.7 1.51e+00 -0.2 4.60e-01 5.66e-01h 1\n", + " 184r 0.0000000e+00 4.46e+02 4.37e+02 -1.7 1.26e+03 - 5.85e-01 2.25e-02h 1\n", + " 185r 0.0000000e+00 3.62e+02 5.95e+02 -1.7 1.17e+03 - 3.15e-01 2.25e-01h 1\n", + " 186r 0.0000000e+00 3.47e+02 2.11e+02 -1.7 6.54e-01 -0.7 4.90e-01 4.12e-02h 1\n", + " 187r 0.0000000e+00 2.68e+02 4.10e+02 -1.7 9.73e+02 - 1.74e-01 2.84e-01h 1\n", + " 188r 0.0000000e+00 2.32e+02 7.23e+02 -1.7 1.37e+03 - 7.54e-01 3.83e-01h 1\n", + " 189r 0.0000000e+00 2.25e+02 1.95e+02 -1.7 7.05e+02 - 6.62e-01 3.01e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 190r 0.0000000e+00 1.61e+02 3.01e+02 -1.7 4.09e+02 - 1.00e+00 3.03e-01h 1\n", + " 191r 0.0000000e+00 9.61e-01 6.13e-01 -1.7 6.25e+01 - 1.00e+00 1.00e+00h 1\n", + " 192r 0.0000000e+00 5.56e-02 3.83e-02 -1.7 6.74e+00 - 1.00e+00 1.00e+00h 1\n", + " 193r 0.0000000e+00 3.80e-01 2.41e+01 -3.9 2.90e+01 - 9.11e-01 7.83e-01f 1\n", + " 194r 0.0000000e+00 2.60e+00 2.67e+01 -3.9 4.29e+04 - 7.72e-02 5.58e-02f 1\n", + " 195r 0.0000000e+00 2.60e+00 3.11e+02 -3.9 2.37e+04 - 6.85e-02 1.39e-05h 1\n", + " 196r 0.0000000e+00 2.91e+00 2.90e+02 -3.9 3.11e+03 - 1.53e-01 3.55e-02f 1\n", + " 197r 0.0000000e+00 1.00e+01 2.50e+02 -3.9 2.55e+03 - 1.71e-01 1.67e-01f 1\n", + " 198r 0.0000000e+00 2.87e+01 3.43e+02 -3.9 2.12e+03 - 7.25e-02 3.31e-01f 1\n", + " 199r 0.0000000e+00 4.82e+01 9.78e+02 -3.9 1.55e+03 - 5.38e-02 5.45e-01f 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 200r 0.0000000e+00 1.40e+02 6.78e+02 -3.9 3.21e+04 - 2.94e-02 1.88e-01f 1\n", + " 201r 0.0000000e+00 1.38e+02 6.81e+02 -3.9 2.53e+04 - 4.87e-02 1.94e-02h 1\n", + " 202r 0.0000000e+00 1.43e+02 6.07e+02 -3.9 2.53e+04 - 2.36e-02 7.13e-02f 1\n", + " 203r 0.0000000e+00 2.17e+02 4.73e+02 -3.9 2.36e+04 - 9.43e-02 1.98e-01f 1\n", + " 204r 0.0000000e+00 2.11e+02 5.82e+02 -3.9 1.89e+04 - 5.56e-01 6.52e-02h 1\n", + " 205r 0.0000000e+00 2.11e+02 7.24e+02 -3.9 1.33e+04 - 8.62e-01 3.50e-03h 1\n", + " 206r 0.0000000e+00 1.88e+02 8.64e+02 -3.9 3.55e+02 - 1.00e+00 1.09e-01h 1\n", + " 207r 0.0000000e+00 3.04e+01 5.52e+02 -3.9 3.16e+02 - 2.11e-01 8.62e-01h 1\n", + " 208r 0.0000000e+00 7.41e-01 1.91e+00 -3.9 4.38e+01 - 1.00e+00 9.97e-01h 1\n", + " 209r 0.0000000e+00 7.13e-01 6.42e+02 -3.9 1.50e-01 - 7.36e-02 3.78e-02h 1\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 210r 0.0000000e+00 5.37e-03 4.03e+02 -3.9 1.44e-01 - 5.86e-01 1.00e+00h 1\n", + " 211r 0.0000000e+00 5.37e-03 2.68e-04 -3.9 2.52e-03 - 1.00e+00 1.00e+00h 1\n", + " 212r 0.0000000e+00 5.37e-03 5.94e+01 -5.9 3.33e-01 - 1.00e+00 6.67e-01f 1\n", + " 213r 0.0000000e+00 4.67e+01 1.51e+02 -5.9 2.60e+04 - 1.03e-01 2.28e-02f 1\n", + " 214r 0.0000000e+00 4.67e+01 8.78e+02 -5.9 4.07e+02 - 8.75e-01 9.73e-07h 2\n", + " 215r 0.0000000e+00 1.68e+01 2.98e+02 -5.9 1.59e-01 - 8.59e-01 6.40e-01h 1\n", + " 216r 0.0000000e+00 2.59e+00 5.90e+01 -5.9 3.25e-02 - 1.00e+00 8.46e-01h 1\n", + " 217r 0.0000000e+00 1.57e-04 3.42e-04 -5.9 3.65e-03 - 1.00e+00 1.00e+00h 1\n", + " 218r 0.0000000e+00 2.69e-09 6.22e-06 -5.9 2.22e-04 - 1.00e+00 1.00e+00h 1\n", "\n", - "Number of Iterations....: 4\n", + "Number of Iterations....: 218\n", "\n", " (scaled) (unscaled)\n", "Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n", "Dual infeasibility......: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Constraint violation....: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Constraint violation....: 2.6943874215090702e-09 2.6943874215090702e-09\n", "Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Overall NLP error.......: 4.5247361413203180e-09 4.5247361413203180e-09\n", + "Overall NLP error.......: 2.6943874215090702e-09 2.6943874215090702e-09\n", "\n", "\n", - "Number of objective function evaluations = 5\n", - "Number of objective gradient evaluations = 5\n", - "Number of equality constraint evaluations = 5\n", + "Number of objective function evaluations = 225\n", + "Number of objective gradient evaluations = 8\n", + "Number of equality constraint evaluations = 225\n", "Number of inequality constraint evaluations = 0\n", - "Number of equality constraint Jacobian evaluations = 5\n", + "Number of equality constraint Jacobian evaluations = 220\n", "Number of inequality constraint Jacobian evaluations = 0\n", - "Number of Lagrangian Hessian evaluations = 4\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.008\n", - "Total CPU secs in NLP function evaluations = 0.000\n", + "Number of Lagrangian Hessian evaluations = 218\n", + "Total CPU secs in IPOPT (w/o function evaluations) = 0.347\n", + "Total CPU secs in NLP function evaluations = 0.036\n", "\n", "EXIT: Optimal Solution Found.\n" ] } ], - "execution_count": 55 + "execution_count": 46 }, { "cell_type": "code", @@ -2421,8 +1770,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.393870Z", - "start_time": "2025-11-20T21:46:17.390132Z" + "end_time": "2026-01-13T00:12:32.984453200Z", + "start_time": "2026-01-13T00:12:32.973413800Z" } }, "source": [ @@ -2432,7 +1781,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 56 + "execution_count": 47 }, { "cell_type": "markdown", @@ -2457,15 +1806,15 @@ "noauto" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.403453Z", - "start_time": "2025-11-20T21:46:17.400372Z" + "end_time": "2026-01-13T00:12:33.001529600Z", + "start_time": "2026-01-13T00:12:32.990965900Z" } }, "source": [ "# m.fs.visualize(\"HDA-Flowsheet\")" ], "outputs": [], - "execution_count": 57 + "execution_count": 48 }, { "cell_type": "markdown", @@ -2478,8 +1827,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.448969Z", - "start_time": "2025-11-20T21:46:17.421434Z" + "end_time": "2026-01-13T00:12:33.046845800Z", + "start_time": "2026-01-13T00:12:33.009050800Z" } }, "source": [ @@ -2495,19 +1844,22 @@ "Flowsheet : fs Time: 0.0\n", "------------------------------------------------------------------------------------\n", " Stream Table\n", - " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", - " Total Molar Flowrate mole / second 0.30005 0.32004 2.0320 2.0320 2.0320 1.7648 0.26712 1.4119 1.4119 0.17224 0.094878 0.35297\n", - " Total Mole Fraction benzene dimensionless 6.6656e-05 6.2492e-05 0.058732 0.058732 0.17408 0.084499 0.76595 0.084499 0.084499 0.82430 0.66001 0.084499\n", - " Total Mole Fraction toluene dimensionless 0.99987 6.2492e-05 0.15380 0.15380 0.038450 0.0088437 0.23405 0.0088437 0.0088437 0.17570 0.33999 0.0088437\n", - " Total Mole Fraction hydrogen dimensionless 3.3328e-05 0.93738 0.27683 0.27683 0.16148 0.18592 6.9600e-09 0.18592 0.18592 1.0794e-08 1.1376e-15 0.18592\n", - " Total Mole Fraction methane dimensionless 3.3328e-05 0.062492 0.51064 0.51064 0.62599 0.72074 2.6982e-08 0.72074 0.72074 4.1844e-08 4.4103e-15 0.72074\n", - " Temperature kelvin 303.20 303.20 324.54 600.00 822.07 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", - " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", + " Units s01 s02 s03 s04 s05 s06 s07 s08 s09 s10 s11 s12 \n", + " Total Molar Flowrate Liq mole / second 0.30001 2.0000e-05 0.34190 1.6073e-09 5.7340e-09 1.0000e-08 0.26712 1.1139e-06 1.1143e-06 1.0000e-08 0.094878 2.7856e-07\n", + " Total Molar Flowrate Vap mole / second 4.0000e-05 0.32002 1.6901 2.0320 2.0320 1.7648 1.0000e-08 1.4119 1.4119 0.17224 1.0000e-08 0.35297\n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 3.3332e-05 0.50000 0.22733 0.13374 0.63390 0.76595 0.76595 0.76595 0.76595 0.66001 0.66001 0.76595\n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.99997 0.50000 0.77267 0.86626 0.36610 0.23405 0.23405 0.23405 0.23405 0.33999 0.33999 0.23405\n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.25000 3.1248e-05 0.024624 0.058732 0.17408 0.084499 0.084499 0.084499 0.084499 0.82430 0.82430 0.084499\n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.25000 3.1248e-05 0.028601 0.15380 0.038450 0.0088437 0.0088437 0.0088435 0.0088435 0.17570 0.17570 0.0088435\n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.25000 0.93744 0.33283 0.27683 0.16148 0.18592 0.18592 0.18592 0.18592 1.7561e-08 1.7561e-08 0.18592\n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.25000 0.062496 0.61394 0.51064 0.62599 0.72074 0.72074 0.72074 0.72074 4.3265e-08 4.3265e-08 0.72074\n", + " Temperature kelvin 303.20 303.20 324.51 600.00 771.86 325.00 325.00 325.00 325.00 375.00 375.00 325.00\n", + " Pressure pascal 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 3.5000e+05 1.5000e+05 1.5000e+05 3.5000e+05\n", "====================================================================================\n" ] } ], - "execution_count": 58 + "execution_count": 49 }, { "cell_type": "markdown", @@ -2520,8 +1872,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.475550Z", - "start_time": "2025-11-20T21:46:17.472001Z" + "end_time": "2026-01-13T00:12:33.065372900Z", + "start_time": "2026-01-13T00:12:33.055710300Z" } }, "source": [ @@ -2532,11 +1884,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 424513.9640158265\n" + "operating cost = $ 419008.281895999\n" ] } ], - "execution_count": 59 + "execution_count": 50 }, { "cell_type": "code", @@ -2545,17 +1897,17 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.571498Z", - "start_time": "2025-11-20T21:46:17.493194Z" + "end_time": "2026-01-13T00:12:33.160597300Z", + "start_time": "2026-01-13T00:12:33.073483400Z" } }, "source": [ "import pytest\n", "\n", - "assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3)" + "assert value(m.fs.operating_cost) == pytest.approx(419008.28189, abs=1e-3)" ], "outputs": [], - "execution_count": 60 + "execution_count": 51 }, { "cell_type": "markdown", @@ -2568,8 +1920,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.596910Z", - "start_time": "2025-11-20T21:46:17.580529Z" + "end_time": "2026-01-13T00:12:33.179064200Z", + "start_time": "2026-01-13T00:12:33.163247500Z" } }, "source": [ @@ -2592,17 +1944,20 @@ " Variables: \n", "\n", " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 7346.0 : watt : False : (None, None)\n", + " Heat Duty : 7346.7 : watt : False : (None, None)\n", " Pressure Change : -2.0000e+05 : pascal : True : (None, None)\n", "\n", "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units Inlet Vapor Outlet Liquid Outlet\n", - " Total Molar Flowrate mole / second 0.26712 - - \n", - " Total Mole Fraction benzene dimensionless 0.76595 - - \n", - " Total Mole Fraction toluene dimensionless 0.23405 - - \n", - " Total Mole Fraction hydrogen dimensionless 6.9600e-09 - - \n", - " Total Mole Fraction methane dimensionless 2.6982e-08 - - \n", + " Total Molar Flowrate Liq mole / second 0.26712 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 0.76595 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.23405 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.084499 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.0088437 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.18592 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.72074 - - \n", " Temperature kelvin 325.00 - - \n", " Pressure pascal 3.5000e+05 - - \n", " flow_mol_phase Liq mole / second - 1.0000e-08 0.094878 \n", @@ -2611,17 +1966,17 @@ " mole_frac_phase_comp ('Liq', 'toluene') dimensionless - 0.33999 0.33999 \n", " mole_frac_phase_comp ('Vap', 'benzene') dimensionless - 0.82430 0.82430 \n", " mole_frac_phase_comp ('Vap', 'toluene') dimensionless - 0.17570 0.17570 \n", - " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.0794e-08 1.0794e-08 \n", - " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.1844e-08 4.1844e-08 \n", + " mole_frac_phase_comp ('Vap', 'hydrogen') dimensionless - 1.7561e-08 1.7561e-08 \n", + " mole_frac_phase_comp ('Vap', 'methane') dimensionless - 4.3265e-08 4.3265e-08 \n", " temperature kelvin - 375.00 375.00 \n", " pressure pascal - 1.5000e+05 1.5000e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8242963521555956\n" + "benzene purity = 0.8242963450787166\n" ] } ], - "execution_count": 61 + "execution_count": 52 }, { "cell_type": "code", @@ -2630,17 +1985,17 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.619054Z", - "start_time": "2025-11-20T21:46:17.613393Z" + "end_time": "2026-01-13T00:12:33.274448800Z", + "start_time": "2026-01-13T00:12:33.188271400Z" } }, "source": [ "assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3)\n", - "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3)\n", + "assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.67441, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3)" ], "outputs": [], - "execution_count": 62 + "execution_count": 53 }, { "cell_type": "markdown", @@ -2653,8 +2008,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.648524Z", - "start_time": "2025-11-20T21:46:17.638446Z" + "end_time": "2026-01-13T00:12:33.290365100Z", + "start_time": "2026-01-13T00:12:33.276957500Z" } }, "source": [ @@ -2671,18 +2026,21 @@ "name": "stdout", "output_type": "stream", "text": [ - " Units Reactor Light Gases\n", - "Total Molar Flowrate mole / second 2.0320 1.7648 \n", - "Total Mole Fraction benzene dimensionless 0.17408 0.084499 \n", - "Total Mole Fraction toluene dimensionless 0.038450 0.0088437 \n", - "Total Mole Fraction hydrogen dimensionless 0.16148 0.18592 \n", - "Total Mole Fraction methane dimensionless 0.62599 0.72074 \n", - "Temperature kelvin 822.07 325.00 \n", - "Pressure pascal 3.5000e+05 3.5000e+05 \n" + " Units Reactor Light Gases\n", + "Total Molar Flowrate Liq mole / second 5.7340e-09 1.0000e-08 \n", + "Total Molar Flowrate Vap mole / second 2.0320 1.7648 \n", + "Total Mole Fraction ('Liq', 'benzene') dimensionless 0.63390 0.76595 \n", + "Total Mole Fraction ('Liq', 'toluene') dimensionless 0.36610 0.23405 \n", + "Total Mole Fraction ('Vap', 'benzene') dimensionless 0.17408 0.084499 \n", + "Total Mole Fraction ('Vap', 'toluene') dimensionless 0.038450 0.0088437 \n", + "Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.16148 0.18592 \n", + "Total Mole Fraction ('Vap', 'methane') dimensionless 0.62599 0.72074 \n", + "Temperature kelvin 771.86 325.00 \n", + "Pressure pascal 3.5000e+05 3.5000e+05 \n" ] } ], - "execution_count": 63 + "execution_count": 54 }, { "cell_type": "markdown", @@ -2717,15 +2075,15 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.675626Z", - "start_time": "2025-11-20T21:46:17.671136Z" + "end_time": "2026-01-13T00:12:33.307079900Z", + "start_time": "2026-01-13T00:12:33.298304Z" } }, "source": [ "m.fs.objective = Objective(expr=m.fs.operating_cost)" ], "outputs": [], - "execution_count": 64 + "execution_count": 55 }, { "cell_type": "markdown", @@ -2738,8 +2096,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.691883Z", - "start_time": "2025-11-20T21:46:17.687385Z" + "end_time": "2026-01-13T00:12:33.315754900Z", + "start_time": "2026-01-13T00:12:33.308100100Z" } }, "source": [ @@ -2749,7 +2107,7 @@ "m.fs.F102.vap_outlet.temperature.unfix()" ], "outputs": [], - "execution_count": 65 + "execution_count": 56 }, { "cell_type": "markdown", @@ -2775,15 +2133,15 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.707409Z", - "start_time": "2025-11-20T21:46:17.704141Z" + "end_time": "2026-01-13T00:12:33.324956200Z", + "start_time": "2026-01-13T00:12:33.315754900Z" } }, "source": [ "# Todo: Unfix deltaP for F102" ], "outputs": [], - "execution_count": 66 + "execution_count": 57 }, { "cell_type": "code", @@ -2792,8 +2150,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.720592Z", - "start_time": "2025-11-20T21:46:17.717532Z" + "end_time": "2026-01-13T00:12:33.333132300Z", + "start_time": "2026-01-13T00:12:33.324956200Z" } }, "source": [ @@ -2801,7 +2159,7 @@ "m.fs.F102.deltaP.unfix()" ], "outputs": [], - "execution_count": 67 + "execution_count": 58 }, { "cell_type": "code", @@ -2810,15 +2168,15 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.759351Z", - "start_time": "2025-11-20T21:46:17.728327Z" + "end_time": "2026-01-13T00:12:33.360701100Z", + "start_time": "2026-01-13T00:12:33.333132300Z" } }, "source": [ "assert degrees_of_freedom(m) == 5" ], "outputs": [], - "execution_count": 68 + "execution_count": 59 }, { "cell_type": "markdown", @@ -2839,8 +2197,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.779305Z", - "start_time": "2025-11-20T21:46:17.775669Z" + "end_time": "2026-01-13T00:12:33.371189900Z", + "start_time": "2026-01-13T00:12:33.362714700Z" } }, "source": [ @@ -2848,7 +2206,7 @@ "m.fs.H101.outlet.temperature[0].setub(600)" ], "outputs": [], - "execution_count": 69 + "execution_count": 60 }, { "cell_type": "markdown", @@ -2873,15 +2231,15 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.797044Z", - "start_time": "2025-11-20T21:46:17.794614Z" + "end_time": "2026-01-13T00:12:33.388084900Z", + "start_time": "2026-01-13T00:12:33.377308100Z" } }, "source": [ "# Todo: Set the bounds for reactor outlet temperature" ], "outputs": [], - "execution_count": 70 + "execution_count": 61 }, { "cell_type": "code", @@ -2890,8 +2248,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.812504Z", - "start_time": "2025-11-20T21:46:17.807564Z" + "end_time": "2026-01-13T00:12:33.406097200Z", + "start_time": "2026-01-13T00:12:33.395647Z" } }, "source": [ @@ -2900,7 +2258,7 @@ "m.fs.R101.outlet.temperature[0].setub(800)" ], "outputs": [], - "execution_count": 71 + "execution_count": 62 }, { "cell_type": "markdown", @@ -2913,8 +2271,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.827227Z", - "start_time": "2025-11-20T21:46:17.822681Z" + "end_time": "2026-01-13T00:12:33.426888400Z", + "start_time": "2026-01-13T00:12:33.413693900Z" } }, "source": [ @@ -2926,7 +2284,7 @@ "m.fs.F102.vap_outlet.pressure[0].setub(110000)" ], "outputs": [], - "execution_count": 72 + "execution_count": 63 }, { "cell_type": "markdown", @@ -2939,8 +2297,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.848212Z", - "start_time": "2025-11-20T21:46:17.844101Z" + "end_time": "2026-01-13T00:12:33.447188200Z", + "start_time": "2026-01-13T00:12:33.436145800Z" } }, "source": [ @@ -2953,7 +2311,7 @@ ")" ], "outputs": [], - "execution_count": 73 + "execution_count": 64 }, { "cell_type": "markdown", @@ -2978,15 +2336,15 @@ "exercise" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.862411Z", - "start_time": "2025-11-20T21:46:17.859385Z" + "end_time": "2026-01-13T00:12:33.464672600Z", + "start_time": "2026-01-13T00:12:33.453771300Z" } }, "source": [ "# Todo: Add minimum product flow constraint" ], "outputs": [], - "execution_count": 74 + "execution_count": 65 }, { "cell_type": "code", @@ -2995,8 +2353,8 @@ "solution" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.876414Z", - "start_time": "2025-11-20T21:46:17.872250Z" + "end_time": "2026-01-13T00:12:33.481454400Z", + "start_time": "2026-01-13T00:12:33.471763500Z" } }, "source": [ @@ -3009,7 +2367,7 @@ ")" ], "outputs": [], - "execution_count": 75 + "execution_count": 66 }, { "cell_type": "markdown", @@ -3022,15 +2380,15 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:17.890250Z", - "start_time": "2025-11-20T21:46:17.887141Z" + "end_time": "2026-01-13T00:12:33.500096Z", + "start_time": "2026-01-13T00:12:33.487986500Z" } }, "source": [ "m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80)" ], "outputs": [], - "execution_count": 76 + "execution_count": 67 }, { "cell_type": "markdown", @@ -3046,121 +2404,13 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:18.024828Z", - "start_time": "2025-11-20T21:46:17.897344Z" + "end_time": "2026-01-13T00:12:33.630996900Z", + "start_time": "2026-01-13T00:12:33.501556Z" } }, - "source": [ - "results = solver.solve(m, tee=True)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ipopt 3.13.2: linear_solver=\"ma57\"\n", - "max_iter=1000\n", - "nlp_scaling_method=\"user-scaling\"\n", - "tol=1e-08\n", - "option_file_name=\"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\"\n", - "\n", - "Using option file \"C:\\Users\\Tanner\\AppData\\Local\\Temp\\tmpqgb86kxz\\unknown.36084.37884.opt\".\n", - "\n", - "\n", - "******************************************************************************\n", - "This program contains Ipopt, a library for large-scale nonlinear optimization.\n", - " Ipopt is released as open source code under the Eclipse Public License (EPL).\n", - " For more information visit http://projects.coin-or.org/Ipopt\n", - "\n", - "This version of Ipopt was compiled from source code available at\n", - " https://github.com/IDAES/Ipopt as part of the Institute for the Design of\n", - " Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE\n", - " Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.\n", - "\n", - "This version of Ipopt was compiled using HSL, a collection of Fortran codes\n", - " for large-scale scientific computation. All technical papers, sales and\n", - " publicity material resulting from use of the HSL codes within IPOPT must\n", - " contain the following acknowledgement:\n", - " HSL, a collection of Fortran codes for large-scale scientific\n", - " computation. See http://www.hsl.rl.ac.uk.\n", - "******************************************************************************\n", - "\n", - "This is Ipopt version 3.13.2, running with linear solver ma57.\n", - "\n", - "Number of nonzeros in equality constraint Jacobian...: 938\n", - "Number of nonzeros in inequality constraint Jacobian.: 9\n", - "Number of nonzeros in Lagrangian Hessian.............: 504\n", - "\n", - "Reallocating memory for MA57: lfact (10594)\n", - "Total number of variables............................: 224\n", - " variables with only lower bounds: 56\n", - " variables with lower and upper bounds: 151\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 219\n", - "Total number of inequality constraints...............: 3\n", - " inequality constraints with only lower bounds: 2\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 1\n", - "\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 0 4.2451396e+05 4.00e+04 6.94e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", - "Reallocating memory for MA57: lfact (11249)\n", - " 1 4.2182392e+05 4.00e+04 6.94e+00 -1.0 3.47e+07 - 3.71e-05 1.25e-05f 1\n", - " 2 4.2170773e+05 4.00e+04 8.41e+01 -1.0 1.49e+06 - 3.32e-04 1.53e-05f 1\n", - " 3 4.1795462e+05 4.00e+04 6.82e+01 -1.0 1.43e+06 - 4.98e-04 5.60e-04f 1\n", - " 4 3.0650178e+05 4.00e+04 3.09e+02 -1.0 1.26e+07 - 2.61e-05 1.17e-03f 1\n", - " 5 3.0553183e+05 3.99e+04 3.25e+04 -1.0 1.48e+05 - 1.28e-01 1.02e-03f 1\n", - " 6 3.0565526e+05 3.91e+04 5.25e+04 -1.0 3.99e+04 - 1.13e-01 2.09e-02h 2\n", - " 7 3.0601574e+05 3.59e+04 4.21e+04 -1.0 3.91e+04 - 5.17e-02 8.21e-02h 2\n", - " 8 3.0674242e+05 2.95e+04 8.41e+04 -1.0 3.59e+04 - 4.38e-01 1.79e-01h 1\n", - " 9 3.1153051e+05 1.11e+04 5.73e+04 -1.0 2.95e+04 - 8.56e-01 6.23e-01h 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 10 3.1154545e+05 1.09e+04 5.69e+04 -1.0 1.19e+04 - 6.57e-02 2.37e-02h 1\n", - " 11 3.1159568e+05 1.08e+04 5.66e+04 -1.0 1.68e+04 - 2.23e-02 8.97e-03h 1\n", - " 12 3.1610911e+05 2.56e+03 2.13e+05 -1.0 1.68e+04 - 9.47e-01 7.94e-01h 1\n", - " 13 3.1708718e+05 1.16e+03 9.56e+04 -1.0 4.45e+03 - 9.90e-01 5.53e-01h 1\n", - " 14 3.1796760e+05 4.06e+02 1.14e+03 -1.0 1.27e+04 - 9.95e-01 9.87e-01h 1\n", - " 15 3.1802429e+05 5.35e+00 6.53e+02 -1.0 8.29e+01 - 1.00e+00 9.89e-01h 1\n", - " 16 3.1802524e+05 1.77e-04 5.89e+02 -1.0 5.10e-01 - 1.00e+00 1.00e+00h 1\n", - " 17 3.1802492e+05 5.34e-06 1.83e+06 -2.5 1.32e+00 - 3.33e-01 1.00e+00f 1\n", - " 18 3.1802492e+05 1.70e-09 9.74e-03 -2.5 2.42e-02 - 1.00e+00 1.00e+00h 1\n", - " 19 3.1802491e+05 4.41e-09 1.03e-01 -5.7 3.83e-02 - 1.00e+00 1.00e+00f 1\n", - "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", - " 20 3.1802491e+05 2.39e-03 8.22e-09 -5.7 2.88e+01 - 1.00e+00 1.00e+00h 1\n", - " 21 3.1802491e+05 8.00e-11 9.72e-09 -5.7 4.08e-04 - 1.00e+00 1.00e+00h 1\n", - " 22 3.1802491e+05 2.47e-03 1.19e-01 -8.6 2.93e+01 - 9.99e-01 1.00e+00h 1\n", - " 23 3.1802491e+05 2.41e+02 2.13e-09 -8.6 9.27e+03 - 1.00e+00 1.00e+00h 1\n", - " 24 3.1802491e+05 6.96e-03 3.66e-09 -8.6 1.88e+02 - 1.00e+00 1.00e+00h 1\n", - " 25 3.1802491e+05 3.61e-06 1.59e-09 -8.6 1.21e+00 - 1.00e+00 1.00e+00h 1\n", - " 26 3.1802491e+05 2.29e-05 4.82e-09 -8.6 3.07e+00 - 1.00e+00 1.00e+00h 1\n", - " 27 3.1802491e+05 9.42e-07 5.47e-09 -8.6 6.24e-01 - 1.00e+00 1.00e+00h 1\n", - " 28 3.1802491e+05 1.16e-10 9.67e-09 -8.6 3.01e+00 - 1.00e+00 1.00e+00H 1\n", - "\n", - "Number of Iterations....: 28\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 3.1802490940142004e+05 3.1802490940142004e+05\n", - "Dual infeasibility......: 9.6706583658121551e-09 9.6706583658121551e-09\n", - "Constraint violation....: 1.1641532182693481e-10 1.1641532182693481e-10\n", - "Complementarity.........: 2.5059899579272651e-09 2.5059899579272651e-09\n", - "Overall NLP error.......: 2.2246107350021195e-10 9.6706583658121551e-09\n", - "\n", - "\n", - "Number of objective function evaluations = 35\n", - "Number of objective gradient evaluations = 29\n", - "Number of equality constraint evaluations = 35\n", - "Number of inequality constraint evaluations = 35\n", - "Number of equality constraint Jacobian evaluations = 29\n", - "Number of inequality constraint Jacobian evaluations = 29\n", - "Number of Lagrangian Hessian evaluations = 28\n", - "Total CPU secs in IPOPT (w/o function evaluations) = 0.036\n", - "Total CPU secs in NLP function evaluations = 0.006\n", - "\n", - "EXIT: Optimal Solution Found.\n" - ] - } - ], - "execution_count": 77 + "source": "results = solver.solve(m, tee=False)", + "outputs": [], + "execution_count": 68 }, { "cell_type": "code", @@ -3169,8 +2419,8 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:18.045752Z", - "start_time": "2025-11-20T21:46:18.041549Z" + "end_time": "2026-01-13T00:12:33.650287300Z", + "start_time": "2026-01-13T00:12:33.639146Z" } }, "source": [ @@ -3180,7 +2430,7 @@ "assert results.solver.termination_condition == TerminationCondition.optimal" ], "outputs": [], - "execution_count": 78 + "execution_count": 69 }, { "cell_type": "markdown", @@ -3195,8 +2445,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:18.074231Z", - "start_time": "2025-11-20T21:46:18.053675Z" + "end_time": "2026-01-13T00:12:33.700975700Z", + "start_time": "2026-01-13T00:12:33.660461600Z" } }, "source": [ @@ -3219,7 +2469,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "operating cost = $ 318024.90940142004\n", + "operating cost = $ 312674.2367537996\n", "\n", "Product flow rate and purity in F102\n", "\n", @@ -3231,17 +2481,20 @@ " Variables: \n", "\n", " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : 8369.3 : watt : False : (None, None)\n", + " Heat Duty : 8370.2 : watt : False : (None, None)\n", " Pressure Change : -2.4500e+05 : pascal : False : (None, None)\n", "\n", "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units Inlet Vapor Outlet Liquid Outlet\n", - " Total Molar Flowrate mole / second 0.28812 - - \n", - " Total Mole Fraction benzene dimensionless 0.75463 - - \n", - " Total Mole Fraction toluene dimensionless 0.24537 - - \n", - " Total Mole Fraction hydrogen dimensionless 7.5018e-09 - - \n", - " Total Mole Fraction methane dimensionless 2.5957e-08 - - \n", + " Total Molar Flowrate Liq mole / second 0.28812 - - \n", + " Total Molar Flowrate Vap mole / second 1.0000e-08 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 0.75463 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.24537 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.032748 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.0032478 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.21614 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.74786 - - \n", " Temperature kelvin 301.88 - - \n", " Pressure pascal 3.5000e+05 - - \n", " flow_mol_phase Liq mole / second - 1.0000e-08 0.10493 \n", @@ -3256,7 +2509,7 @@ " pressure pascal - 1.0500e+05 1.0500e+05 \n", "====================================================================================\n", "\n", - "benzene purity = 0.8188295888411846\n", + "benzene purity = 0.8188295888412465\n", "\n", "Overhead loss in F101\n", "\n", @@ -3268,18 +2521,21 @@ " Variables: \n", "\n", " Key : Value : Units : Fixed : Bounds\n", - " Heat Duty : -66423. : watt : False : (None, None)\n", + " Heat Duty : -68347. : watt : False : (None, None)\n", " Pressure Change : 0.0000 : pascal : True : (None, None)\n", "\n", "------------------------------------------------------------------------------------\n", " Stream Table\n", " Units Inlet Vapor Outlet Liquid Outlet\n", - " Total Molar Flowrate mole / second 1.9480 - - \n", - " Total Mole Fraction benzene dimensionless 0.13952 - - \n", - " Total Mole Fraction toluene dimensionless 0.039059 - - \n", - " Total Mole Fraction hydrogen dimensionless 0.18417 - - \n", - " Total Mole Fraction methane dimensionless 0.63725 - - \n", - " Temperature kelvin 763.51 - - \n", + " Total Molar Flowrate Liq mole / second 1.5819e-12 - - \n", + " Total Molar Flowrate Vap mole / second 1.9480 - - \n", + " Total Mole Fraction ('Liq', 'benzene') dimensionless 0.57381 - - \n", + " Total Mole Fraction ('Liq', 'toluene') dimensionless 0.42619 - - \n", + " Total Mole Fraction ('Vap', 'benzene') dimensionless 0.13952 - - \n", + " Total Mole Fraction ('Vap', 'toluene') dimensionless 0.039059 - - \n", + " Total Mole Fraction ('Vap', 'hydrogen') dimensionless 0.18417 - - \n", + " Total Mole Fraction ('Vap', 'methane') dimensionless 0.63725 - - \n", + " Temperature kelvin 775.95 - - \n", " Pressure pascal 3.5000e+05 - - \n", " flow_mol_phase Liq mole / second - 1.0000e-08 0.28812 \n", " flow_mol_phase Vap mole / second - 1.6598 1.0000e-08 \n", @@ -3295,7 +2551,7 @@ ] } ], - "execution_count": 79 + "execution_count": 70 }, { "cell_type": "code", @@ -3304,16 +2560,16 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:18.093619Z", - "start_time": "2025-11-20T21:46:18.090039Z" + "end_time": "2026-01-13T00:12:33.717027100Z", + "start_time": "2026-01-13T00:12:33.703994500Z" } }, "source": [ - "assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3)\n", + "assert value(m.fs.operating_cost) == pytest.approx(312674.236, abs=1e-3)\n", "assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3)" ], "outputs": [], - "execution_count": 80 + "execution_count": 71 }, { "cell_type": "markdown", @@ -3326,8 +2582,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2025-11-20T21:46:18.106001Z", - "start_time": "2025-11-20T21:46:18.101768Z" + "end_time": "2026-01-13T00:12:33.735319500Z", + "start_time": "2026-01-13T00:12:33.718148400Z" } }, "source": [ @@ -3354,7 +2610,7 @@ "\n", "H101 outlet temperature = 500.000 K\n", "\n", - "R101 outlet temperature = 763.507 K\n", + "R101 outlet temperature = 775.947 K\n", "\n", "F101 outlet temperature = 301.881 K\n", "\n", @@ -3364,7 +2620,7 @@ ] } ], - "execution_count": 81 + "execution_count": 72 }, { "cell_type": "code", @@ -3373,39 +2629,19 @@ "testing" ], "ExecuteTime": { - "end_time": "2025-11-20T21:46:19.262061Z", - "start_time": "2025-11-20T21:46:18.121920Z" + "end_time": "2026-01-13T00:12:33.750045300Z", + "start_time": "2026-01-13T00:12:33.736837800Z" } }, "source": [ "assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3)\n", - "print(value(m.fs.R101.outlet.temperature[0]))\n", - "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3)\n", + "assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(775.947, abs=1e-3)\n", "assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3)\n", "assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "763.5072359720118\n" - ] - }, - { - "ename": "AssertionError", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mAssertionError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[82]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.H101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m500\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]))\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.R101.outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m763.484\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F101.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m301.881\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n\u001b[32m 5\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m value(m.fs.F102.vap_outlet.temperature[\u001b[32m0\u001b[39m]) == pytest.approx(\u001b[32m362.935\u001b[39m, \u001b[38;5;28mabs\u001b[39m=\u001b[32m1e-3\u001b[39m)\n", - "\u001b[31mAssertionError\u001b[39m: " - ] - } - ], - "execution_count": 82 + "outputs": [], + "execution_count": 73 } ], "metadata": { diff --git a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py index 57eac3e4..ff0ca779 100644 --- a/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py +++ b/idaes_examples/notebooks/docs/tut/core/hda_flowsheet.py @@ -7,9 +7,10 @@ TransformationFactory, value, ) -from pyomo.network import Arc, SequentialDecomposition - +from pyomo.network import Arc from idaes.core import FlowsheetBlock +from idaes.core.util.model_statistics import degrees_of_freedom +from idaes.core.solvers import get_solver from idaes.models.unit_models import ( PressureChanger, @@ -19,561 +20,255 @@ StoichiometricReactor, Feed, Product, + Flash, ) - -from idaes.core.util.exceptions import InitializationError -import idaes.logger as idaeslog - -# Todo: import flash model from idaes.models.unit_models - -# Todo: import flash model from idaes.models.unit_models -from idaes.models.unit_models import Flash - from idaes.models.unit_models.pressure_changer import ThermodynamicAssumption -from idaes.core.util.model_statistics import degrees_of_freedom - -from idaes.core.solvers import get_solver - from idaes.models.properties.modular_properties.base.generic_property import ( GenericParameterBlock, ) from idaes.models.properties.modular_properties.base.generic_reaction import ( GenericReactionParameterBlock, ) + from idaes_examples.mod.hda.hda_ideal_VLE_modular import thermo_config from idaes_examples.mod.hda.hda_reaction_modular import reaction_config +from idaes_examples.mod.hda.hda_flowsheet_extras import manual_propagation, automatic_propagation, fix_inlet_states -m = ConcreteModel() -m.fs = FlowsheetBlock(dynamic=False) -m.fs.thermo_params = GenericParameterBlock(**thermo_config) -m.fs.reaction_params = GenericReactionParameterBlock( - property_package=m.fs.thermo_params, **reaction_config -) +if __name__ == "__main__": + m = ConcreteModel() + m.fs = FlowsheetBlock(dynamic=False) -m.fs.I101 = Feed(property_package=m.fs.thermo_params) -m.fs.I102 = Feed(property_package=m.fs.thermo_params) + m.fs.thermo_params = GenericParameterBlock(**thermo_config) + m.fs.reaction_params = GenericReactionParameterBlock( + property_package=m.fs.thermo_params, **reaction_config + ) -m.fs.M101 = Mixer( - property_package=m.fs.thermo_params, - num_inlets=3, -) + m.fs.I101 = Feed(property_package=m.fs.thermo_params) + m.fs.I102 = Feed(property_package=m.fs.thermo_params) -m.fs.H101 = Heater( - property_package=m.fs.thermo_params, - has_pressure_change=False, - has_phase_equilibrium=True, -) + m.fs.M101 = Mixer( + property_package=m.fs.thermo_params, + num_inlets=3, + ) -m.fs.R101 = StoichiometricReactor( - property_package=m.fs.thermo_params, - reaction_package=m.fs.reaction_params, - has_heat_of_reaction=True, - has_heat_transfer=True, - has_pressure_change=False, -) + m.fs.H101 = Heater( + property_package=m.fs.thermo_params, + has_pressure_change=False, + has_phase_equilibrium=True, + ) -m.fs.F101 = Flash( - property_package=m.fs.thermo_params, - has_heat_transfer=True, - has_pressure_change=True, -) + m.fs.R101 = StoichiometricReactor( + property_package=m.fs.thermo_params, + reaction_package=m.fs.reaction_params, + has_heat_of_reaction=True, + has_heat_transfer=True, + has_pressure_change=False, + ) -m.fs.S101 = Splitter( - property_package=m.fs.thermo_params, - ideal_separation=False, - outlet_list=["purge", "recycle"], -) + m.fs.F101 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, + ) -m.fs.C101 = PressureChanger( - property_package=m.fs.thermo_params, - compressor=True, - thermodynamic_assumption=ThermodynamicAssumption.isothermal, -) + m.fs.S101 = Splitter( + property_package=m.fs.thermo_params, + ideal_separation=False, + outlet_list=["purge", "recycle"], + ) -m.fs.F102 = Flash( - property_package=m.fs.thermo_params, - has_heat_transfer=True, - has_pressure_change=True, -) + m.fs.C101 = PressureChanger( + property_package=m.fs.thermo_params, + compressor=True, + thermodynamic_assumption=ThermodynamicAssumption.isothermal, + ) -m.fs.P101 = Product(property_package=m.fs.thermo_params) -m.fs.P102 = Product(property_package=m.fs.thermo_params) -m.fs.P103 = Product(property_package=m.fs.thermo_params) - -m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1) -m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2) -m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet) -m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet) -m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet) -m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet) -m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet) -m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet) -m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3) -m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet) -m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet) -m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet) - -TransformationFactory("network.expand_arcs").apply_to(m) - -m.fs.purity = Expression( - expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ - "Vap", "benzene" - ] - / ( - m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] - + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ - "Vap", "toluene" - ] + m.fs.F102 = Flash( + property_package=m.fs.thermo_params, + has_heat_transfer=True, + has_pressure_change=True, ) -) -m.fs.cooling_cost = Expression( - expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0]) -) + m.fs.P101 = Product(property_package=m.fs.thermo_params) + m.fs.P102 = Product(property_package=m.fs.thermo_params) + m.fs.P103 = Product(property_package=m.fs.thermo_params) + + m.fs.s01 = Arc(source=m.fs.I101.outlet, destination=m.fs.M101.inlet_1) + m.fs.s02 = Arc(source=m.fs.I102.outlet, destination=m.fs.M101.inlet_2) + m.fs.s03 = Arc(source=m.fs.M101.outlet, destination=m.fs.H101.inlet) + m.fs.s04 = Arc(source=m.fs.H101.outlet, destination=m.fs.R101.inlet) + m.fs.s05 = Arc(source=m.fs.R101.outlet, destination=m.fs.F101.inlet) + m.fs.s06 = Arc(source=m.fs.F101.vap_outlet, destination=m.fs.S101.inlet) + m.fs.s07 = Arc(source=m.fs.F101.liq_outlet, destination=m.fs.F102.inlet) + m.fs.s08 = Arc(source=m.fs.S101.recycle, destination=m.fs.C101.inlet) + m.fs.s09 = Arc(source=m.fs.C101.outlet, destination=m.fs.M101.inlet_3) + m.fs.s10 = Arc(source=m.fs.F102.vap_outlet, destination=m.fs.P101.inlet) + m.fs.s11 = Arc(source=m.fs.F102.liq_outlet, destination=m.fs.P102.inlet) + m.fs.s12 = Arc(source=m.fs.S101.purge, destination=m.fs.P103.inlet) + + TransformationFactory("network.expand_arcs").apply_to(m) + + m.fs.purity = Expression( + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + / ( + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] + + m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "toluene" + ] + ) + ) -m.fs.heating_cost = Expression( - expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0] -) + m.fs.cooling_cost = Expression( + expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) + 0.212e-7 * (-m.fs.R101.heat_duty[0]) + ) -m.fs.operating_cost = Expression( - expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) -) + m.fs.heating_cost = Expression( + expr=2.2e-7 * m.fs.H101.heat_duty[0] + 1.9e-7 * m.fs.F102.heat_duty[0] + ) -assert degrees_of_freedom(m) == 29 - -F_liq_toluene = 0.30 -F_liq_non_zero = 1e-5 - -F_vap_I101 = F_liq_non_zero * 4 -F_liq_I101 = F_liq_toluene + F_liq_non_zero - -m.fs.I101.flow_mol_phase[0, "Vap"].fix(F_vap_I101) -m.fs.I101.flow_mol_phase[0, "Liq"].fix(F_liq_I101) -m.fs.I101.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_liq_non_zero / F_vap_I101) -m.fs.I101.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_liq_non_zero / F_vap_I101) -m.fs.I101.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_liq_non_zero / F_vap_I101) -m.fs.I101.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_liq_non_zero / F_vap_I101) -m.fs.I101.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I101) -m.fs.I101.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_toluene / F_liq_I101) -m.fs.I101.temperature.fix(303.2) -m.fs.I101.pressure.fix(350000) - -F_vap_hydrogen = 0.30 -F_vap_methane = 0.020 - -F_vap_non_zero = 1e-5 -F_liq_non_zero = F_vap_non_zero - -F_vap_I102 = F_vap_hydrogen + F_vap_methane + 2 * F_vap_non_zero -F_liq_I102 = 2 * F_vap_non_zero - -m.fs.I102.flow_mol_phase[0, "Vap"].fix(F_vap_I102) -m.fs.I102.flow_mol_phase[0, "Liq"].fix(F_liq_I102) -m.fs.I102.mole_frac_phase_comp[0, "Vap", "benzene"].fix(F_vap_non_zero / F_vap_I102) -m.fs.I102.mole_frac_phase_comp[0, "Vap", "toluene"].fix(F_vap_non_zero / F_vap_I102) -m.fs.I102.mole_frac_phase_comp[0, "Vap", "hydrogen"].fix(F_vap_hydrogen / F_vap_I102) -m.fs.I102.mole_frac_phase_comp[0, "Vap", "methane"].fix(F_vap_methane / F_vap_I102) -m.fs.I102.mole_frac_phase_comp[0, "Liq", "benzene"].fix(F_liq_non_zero / F_liq_I102) -m.fs.I102.mole_frac_phase_comp[0, "Liq", "toluene"].fix(F_liq_non_zero / F_liq_I102) - -m.fs.I102.temperature.fix(303.2) -m.fs.I102.pressure.fix(350000) - -m.fs.H101.outlet.temperature.fix(600) - -m.fs.R101.conversion = Var(initialize=0.75, bounds=(0, 1)) - -m.fs.R101.conv_constraint = Constraint( - expr=m.fs.R101.conversion - * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"]) - == ( - m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"] - - m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp[ - "Vap", "toluene" - ] + m.fs.operating_cost = Expression( + expr=(3600 * 24 * 365 * (m.fs.heating_cost + m.fs.cooling_cost)) ) -) -m.fs.R101.conversion.fix(0.75) -m.fs.R101.heat_duty.fix(0) - -m.fs.F101.vap_outlet.temperature.fix(325.0) -m.fs.F101.deltaP.fix(0) - -m.fs.F102.vap_outlet.temperature.fix(375) -m.fs.F102.deltaP.fix(-200000) - -m.fs.S101.split_fraction[0, "purge"].fix(0.2) -m.fs.C101.outlet.pressure.fix(350000) - -seq = SequentialDecomposition() -seq.options.select_tear_method = "heuristic" -seq.options.tear_method = "Wegstein" -seq.options.iterLim = 3 - -# Using the SD tool -G = seq.create_graph(m) -heuristic_tear_set = seq.tear_set_arcs(G, method="heuristic") -order = seq.calculation_order(G) - -for o in heuristic_tear_set: - print(o.name) - -for o in order: - print(o[0].name) - -tear_guesses = { - "flow_mol_phase": { - (0, "Liq"): F_liq_I101, - (0, "Vap"): F_vap_I102, - }, - "mole_frac_phase_comp": { - (0, "Liq", "benzene"): 1e-5 / F_liq_I101, - (0, "Liq", "toluene"): 0.30 / F_liq_I101, - (0, "Vap", "benzene"): 1e-5 / F_vap_I102, - (0, "Vap", "toluene"): 1e-5 / F_vap_I102, - (0, "Vap", "methane"): 0.02 / F_vap_I102, - (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, - }, - "temperature": {0: 303}, - "pressure": {0: 350000}, -} - -# Pass the tear_guess to the SD tool -seq.set_guesses_for(m.fs.H101.inlet, tear_guesses) - - -def function(unit): - try: - initializer = unit.default_initializer() - initializer.initialize(unit, output_level=idaeslog.INFO) - except InitializationError: - solver = get_solver() - solver.solve(unit) - - -seq.run(m, function) - -# from idaes.core.util.initialization import propagate_state -# -# print(f"The DOF is {degrees_of_freedom(m)} initially") -# m.fs.s03_expanded.deactivate() -# print(f"The DOF is {degrees_of_freedom(m)} after deactivating the tear stream") -# -# tear_guesses = { -# "flow_mol_phase": { -# (0, "Liq"): F_liq_I101, -# (0, "Vap"): F_vap_I102, -# -# }, -# "mole_frac_phase_comp": { -# (0, "Liq", "benzene"): 1e-5 / F_liq_I101, -# (0, "Liq", "toluene"): 0.30 / F_liq_I101, -# (0, "Vap", "benzene"): 1e-5 / F_vap_I102, -# (0, "Vap", "toluene"): 1e-5 / F_vap_I102, -# (0, "Vap", "methane"): 0.02 / F_vap_I102, -# (0, "Vap", "hydrogen"): 0.30 / F_vap_I102, -# }, -# "temperature": {0: 303}, -# "pressure": {0: 350000}, -# } -# -# for k, v in tear_guesses.items(): -# for k1, v1 in v.items(): -# getattr(m.fs.s03.destination, k)[k1].fix(v1) -# -# DOF_initial = degrees_of_freedom(m) -# -# print(f"The DOF is {degrees_of_freedom(m)} after setting the tear stream") -# -# m.fs.H101.default_initializer().initialize(m.fs.H101) -# propagate_state(m.fs.s04) # Establish connection between Heater and Reactor -# m.fs.R101.default_initializer().initialize(m.fs.R101) # Initialize Reactor -# propagate_state(m.fs.s05) # Establish connection between Reactor and First Flash Unit -# m.fs.F101.default_initializer().initialize(m.fs.F101) # Initialize First Flash Unit -# propagate_state(m.fs.s06) # Establish connection between First Flash Unit and Splitter -# propagate_state(m.fs.s07) -# m.fs.S101.default_initializer().initialize(m.fs.S101) # Initialize Splitter -# propagate_state(m.fs.s08) # Establish connection between Splitter and Compressor -# m.fs.C101.default_initializer().initialize(m.fs.C101) # Initialize Compressor -# propagate_state(m.fs.s09) # Establish connection between Compressor and Mixer -# m.fs.I101.default_initializer().initialize(m.fs.I101) # Initialize Toluene Inlet -# propagate_state(m.fs.s01) # Establish connection between Toluene Inlet and Mixer -# m.fs.I102.default_initializer().initialize(m.fs.I102) # Initialize Hydrogen Inlet -# propagate_state(m.fs.s02) # Establish connection between Hydrogen Inlet and Mixer -# m.fs.M101.default_initializer().initialize(m.fs.M101) # Initialize Mixer -# propagate_state(m.fs.s03) # Establish connection between Mixer and Heater -# m.fs.F102.default_initializer().initialize(m.fs.F102) # Initialize Second Flash Unit -# propagate_state(m.fs.s10) # Establish connection between Second Flash Unit and Benzene Product -# propagate_state(m.fs.s11) # Establish connection between Second Flash Unit and Toluene Product -# propagate_state(m.fs.s12) # Establish connection between Splitter and Purge Product - -optarg = { - "nlp_scaling_method": "user-scaling", - "OF_ma57_automatic_scaling": "yes", - "max_iter": 300, - "tol": 1e-8, -} -solver = get_solver("ipopt_v2", options=optarg) -results = solver.solve(m, tee=True) - -for k, v in tear_guesses.items(): - for k1, v1 in v.items(): - getattr(m.fs.H101.inlet, k)[k1].unfix() - -m.fs.s03_expanded.activate() -print( - f"The DOF is {degrees_of_freedom(m)} after unfixing the values and reactivating the tear stream" -) -# %% md -# ## 6 Solving the Model -# %% md -# We have now initialized the flowsheet. Lets set up some solving options before simulating the flowsheet. We want to specify the scaling method, number of iterations, and tolerance. More specific or advanced options can be found at the documentation for IPOPT https://coin-or.github.io/Ipopt/OPTIONS.html -# %% -optarg = { - "nlp_scaling_method": "user-scaling", - "OF_ma57_automatic_scaling": "yes", - "max_iter": 1000, - "tol": 1e-8, -} -# %% md -#
-# Inline Exercise: -# Let us run the flowsheet in a simulation mode to look at the results. To do this, complete the last line of code where we pass the model to the solver. You will need to type the following: -# -# solver = get_solver(solver_options=optarg)
-# results = solver.solve(m, tee=True) -# -# Use Shift+Enter to run the cell once you have typed in your code. -#
-# -# %% -# Create the solver object - -# Solve the model -# %% -# Create the solver object -solver = get_solver("ipopt_v2", options=optarg) - -# Solve the model -results = solver.solve(m, tee=False) - -print(f"Solver result: {results}") -# %% -# Check solver solve status -from pyomo.environ import TerminationCondition - -assert results.solver.termination_condition == TerminationCondition.optimal -# %% md -# ## 7 Analyze the results -# -# -# -# %% md -# If the IDAES UI package was installed with the `idaes-pse` installation or installed separately, you can run the flowsheet visualizer to see a full diagram of the full process that is generated and displayed on a browser window. -# -# %% -# m.fs.visualize("HDA-Flowsheet") -# %% md -# Otherwise, we can run the `m.fs.report()` method to see a full summary of the solved flowsheet. It is recommended to adjust the width of the output as much as possible for the cleanest display. -# %% -m.fs.report() -# %% md -# What is the total operating cost? -# %% -print("operating cost = $", value(m.fs.operating_cost)) -# %% -import pytest - -# assert value(m.fs.operating_cost) == pytest.approx(424513.9645, abs=1e-3) -# %% md -# For this operating cost, what is the amount of benzene we are able to produce and what purity we are able to achieve? We can look at a specific unit models stream table with the same `report()` method. -# %% -m.fs.F102.report() - -print() -print("benzene purity = ", value(m.fs.purity)) -# %% -assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) -assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.03097, abs=1e-3) -assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) -# %% md -# Next, let's look at how much benzene we are losing with the light gases out of F101. IDAES has tools for creating stream tables based on the `Arcs` and/or `Ports` in a flowsheet. Let us create and print a simple stream table showing the stream leaving the reactor and the vapor stream from F101. -# %% -from idaes.core.util.tables import ( - create_stream_table_dataframe, - stream_table_dataframe_to_string, -) + assert degrees_of_freedom(m) == 29 -st = create_stream_table_dataframe({"Reactor": m.fs.s05, "Light Gases": m.fs.s06}) -print(stream_table_dataframe_to_string(st)) -# %% md -# ## 8 Optimization -# -# -# We saw from the results above that the total operating cost for the base case was $419,122 per year. We are producing 0.142 mol/s of benzene at a purity of 82\%. However, we are losing around 42\% of benzene in F101 vapor outlet stream. -# -# Let us try to minimize this cost such that: -# - we are producing at least 0.15 mol/s of benzene in F102 vapor outlet i.e. our product stream -# - purity of benzene i.e. the mole fraction of benzene in F102 vapor outlet is at least 80% -# - restricting the benzene loss in F101 vapor outlet to less than 20% -# -# For this problem, our decision variables are as follows: -# - H101 outlet temperature -# - R101 cooling duty provided -# - F101 outlet temperature -# - F102 outlet temperature -# - F102 deltaP in the flash tank -# -# %% md -# Let us declare our objective function for this problem. -# %% -m.fs.objective = Objective(expr=m.fs.operating_cost) -# %% md -# Now, we need to unfix the decision variables as we had solved a square problem (degrees of freedom = 0) until now. -# %% -m.fs.H101.outlet.temperature.unfix() -m.fs.R101.heat_duty.unfix() -m.fs.F101.vap_outlet.temperature.unfix() -m.fs.F102.vap_outlet.temperature.unfix() -# %% md -#
-# Inline Exercise: -# Let us now unfix the remaining variable which is F102 pressure drop (F102.deltaP) -# -# Use Shift+Enter to run the cell once you have typed in your code. -#
-# -# -# %% -# Todo: Unfix deltaP for F102 -# %% -# Todo: Unfix deltaP for F102 -m.fs.F102.deltaP.unfix() -# %% -assert degrees_of_freedom(m) == 5 -# %% md -# Next, we need to set bounds on these decision variables to values shown below: -# -# - H101 outlet temperature [500, 600] K -# - R101 outlet temperature [600, 800] K -# - F101 outlet temperature [298, 450] K -# - F102 outlet temperature [298, 450] K -# - F102 outlet pressure [105000, 110000] Pa -# -# Let us first set the variable bound for the H101 outlet temperature as shown below: -# %% -m.fs.H101.outlet.temperature[0].setlb(500) -m.fs.H101.outlet.temperature[0].setub(600) -# %% md -#
-# Inline Exercise: -# Now, set the variable bound for the R101 outlet temperature. -# -# Use Shift+Enter to run the cell once you have typed in your code. -#
-# %% -# Todo: Set the bounds for reactor outlet temperature -# %% -# Todo: Set the bounds for reactor outlet temperature -m.fs.R101.outlet.temperature[0].setlb(600) -m.fs.R101.outlet.temperature[0].setub(800) -# %% md -# Let us fix the bounds for the rest of the decision variables. -# %% -m.fs.F101.vap_outlet.temperature[0].setlb(298.0) -m.fs.F101.vap_outlet.temperature[0].setub(450.0) -m.fs.F102.vap_outlet.temperature[0].setlb(298.0) -m.fs.F102.vap_outlet.temperature[0].setub(450.0) -m.fs.F102.vap_outlet.pressure[0].setlb(105000) -m.fs.F102.vap_outlet.pressure[0].setub(110000) -# %% md -# Now, the only things left to define are our constraints on overhead loss in F101, product flow rate and purity in F102. Let us first look at defining a constraint for the overhead loss in F101 where we are restricting the benzene leaving the vapor stream to less than 20 \% of the benzene available in the reactor outlet. -# %% -m.fs.overhead_loss = Constraint( - expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp[ - "Vap", "benzene" - ] - <= 0.20 - * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] -) -# %% md -#
-# Inline Exercise: -# Now, add the constraint such that we are producing at least 0.15 mol/s of benzene in the product stream which is the vapor outlet of F102. Let us name this constraint as m.fs.product_flow. -# -# Use Shift+Enter to run the cell once you have typed in your code. -#
-# %% -# Todo: Add minimum product flow constraint -# %% -# Todo: Add minimum product flow constraint -m.fs.product_flow = Constraint( - expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ - "Vap", "benzene" - ] - >= 0.15 -) -# %% md -# Let us add the final constraint on product purity or the mole fraction of benzene in the product stream such that it is at least greater than 80%. -# %% -m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) -# %% md -# -# We have now defined the optimization problem and we are now ready to solve this problem. -# -# -# -# %% -results = solver.solve(m, tee=True) -# %% -# Check for solver solve status -from pyomo.environ import TerminationCondition - -assert results.solver.termination_condition == TerminationCondition.optimal -# %% md -# ### 8.1 Optimization Results -# -# Display the results and product specifications -# %% -print("operating cost = $", value(m.fs.operating_cost)) - -print() -print("Product flow rate and purity in F102") - -m.fs.F102.report() - -print() -print("benzene purity = ", value(m.fs.purity)) - -print() -print("Overhead loss in F101") -m.fs.F101.report() -# %% - -assert value(m.fs.operating_cost) == pytest.approx(318024.909, abs=1e-3) -assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) -# %% md -# Display optimal values for the decision variables -# %% -print( - f"""Optimal Values: - -H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K - -R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K - -F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K - -F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K -F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa -""" -) -# %% -assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) -# assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(696.112, abs=1e-3) -assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(763.484, abs=1e-3) -assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3) -assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) -assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2) + tear_guesses = fix_inlet_states(m) + + m.fs.H101.outlet.temperature.fix(600) + + m.fs.R101.control_volume.conversion = Var(initialize=0.75, bounds=(0, 1)) + + m.fs.R101.conv_constraint = Constraint( + expr=m.fs.R101.control_volume.conversion + * (m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"]) + == ( + m.fs.R101.control_volume.properties_in[0].flow_mol_phase_comp["Vap", "toluene"] - + m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "toluene"]) + ) + + m.fs.R101.control_volume.conversion.fix(0.75) + m.fs.R101.heat_duty.fix(0.0) + + m.fs.F101.vap_outlet.temperature.fix(325.0) + m.fs.F101.deltaP.fix(0.0) + + m.fs.F102.vap_outlet.temperature.fix(375) + m.fs.F102.deltaP.fix(-200000) + + m.fs.S101.split_fraction[0, "purge"].fix(0.2) + m.fs.C101.outlet.pressure.fix(350000) + + # automatic_propagation(m, tear_guesses) + manual_propagation(m, tear_guesses) + + optarg = { + "nlp_scaling_method": "user-scaling", + "OF_ma57_automatic_scaling": "yes", + "max_iter": 1000, + "tol": 1e-8, + } + + solver = get_solver("ipopt_v2", options=optarg) + + # Solve the model + results = solver.solve(m, tee=False) + + from pyomo.environ import TerminationCondition + + assert results.solver.termination_condition == TerminationCondition.optimal + + print("operating cost = $", value(m.fs.operating_cost)) + + import pytest + + print("benzene purity = ", value(m.fs.purity)) + + assert value(m.fs.purity) == pytest.approx(0.82429, abs=1e-3) + + assert value(m.fs.F102.heat_duty[0]) == pytest.approx(7346.67441, abs=1e-3) + assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(1.5000e05, abs=1e-3) + + m.fs.objective = Objective(expr=m.fs.operating_cost) + + m.fs.H101.outlet.temperature.unfix() + m.fs.R101.heat_duty.unfix() + m.fs.F101.vap_outlet.temperature.unfix() + m.fs.F102.vap_outlet.temperature.unfix() + + m.fs.F102.deltaP.unfix() + + assert degrees_of_freedom(m) == 5 + + m.fs.H101.outlet.temperature[0].setlb(500) + m.fs.H101.outlet.temperature[0].setub(600) + + m.fs.R101.outlet.temperature[0].setlb(600) + m.fs.R101.outlet.temperature[0].setub(800) + + m.fs.F101.vap_outlet.temperature[0].setlb(298.0) + m.fs.F101.vap_outlet.temperature[0].setub(450.0) + m.fs.F102.vap_outlet.temperature[0].setlb(298.0) + m.fs.F102.vap_outlet.temperature[0].setub(450.0) + m.fs.F102.vap_outlet.pressure[0].setlb(105000) + m.fs.F102.vap_outlet.pressure[0].setub(110000) + + m.fs.overhead_loss = Constraint( + expr=m.fs.F101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] <= 0.20 + * m.fs.R101.control_volume.properties_out[0].flow_mol_phase_comp["Vap", "benzene"] + ) + + m.fs.product_flow = Constraint( + expr=m.fs.F102.control_volume.properties_out[0].flow_mol_phase_comp[ + "Vap", "benzene" + ] + >= 0.15 + ) + + m.fs.product_purity = Constraint(expr=m.fs.purity >= 0.80) + + results = solver.solve(m, tee=False) + + # Check for solver solve status + from pyomo.environ import TerminationCondition + + assert results.solver.termination_condition == TerminationCondition.optimal + + print("operating cost = $", value(m.fs.operating_cost)) + + print() + print("Product flow rate and purity in F102") + m.fs.F102.report() + + print() + print("benzene purity = ", value(m.fs.purity)) + + print() + print("Overhead loss in F101") + m.fs.F101.report() + + # + assert value(m.fs.operating_cost) == pytest.approx(312674.236, abs=1e-3) + assert value(m.fs.purity) == pytest.approx(0.818827, abs=1e-3) + + print( + f"""Optimal Values: + + H101 outlet temperature = {value(m.fs.H101.outlet.temperature[0]):.3f} K + + R101 outlet temperature = {value(m.fs.R101.outlet.temperature[0]):.3f} K + + F101 outlet temperature = {value(m.fs.F101.vap_outlet.temperature[0]):.3f} K + + F102 outlet temperature = {value(m.fs.F102.vap_outlet.temperature[0]):.3f} K + F102 outlet pressure = {value(m.fs.F102.vap_outlet.pressure[0]):.3f} Pa + """ + ) + + assert value(m.fs.H101.outlet.temperature[0]) == pytest.approx(500, abs=1e-3) + # assert value(m.fs.R101.outlet.temperature[0]) == pytest.approx(862.907, abs=1e-3) + assert value(m.fs.F101.vap_outlet.temperature[0]) == pytest.approx(301.881, abs=1e-3) + assert value(m.fs.F102.vap_outlet.temperature[0]) == pytest.approx(362.935, abs=1e-3) + assert value(m.fs.F102.vap_outlet.pressure[0]) == pytest.approx(105000, abs=1e-2)